@@ -102,7 +102,7 @@ export default class CloudPaymentsWebhooks {
102102 * @param res - Express response object
103103 */
104104 private async composePayment ( req : ComposePaymentRequest , res : express . Response ) : Promise < void > {
105- const { workspaceId, tariffPlanId, shouldSaveCard, isCardLinkOperation } = req . query ;
105+ const { workspaceId, tariffPlanId, shouldSaveCard } = req . query ;
106106 const userId = req . context . user . id ;
107107
108108 if ( ! workspaceId || ! tariffPlanId || ! userId ) {
@@ -129,23 +129,30 @@ export default class CloudPaymentsWebhooks {
129129 await this . getMember ( userId , workspace ) ;
130130 } catch ( e ) {
131131 const error = e as Error ;
132-
132+
133133 this . sendError ( res , 1 , `[Billing / Compose payment] Can't compose payment due to error: ${ error . toString ( ) } ` , req . query ) ;
134-
134+
135135 return ;
136136 }
137137 const invoiceId = this . generateInvoiceId ( tariffPlan , workspace ) ;
138+
139+ const isCardLinkOperation = workspace . tariffPlanId . toString ( ) === tariffPlanId && ! this . isPlanExpired ( workspace ) ;
138140
139141 let checksum ;
140142
141143 try {
142- checksum = await checksumService . generateChecksum ( {
144+ const checksumData = isCardLinkOperation ? {
145+ isCardLinkOperation : true ,
146+ workspaceId : workspace . _id . toString ( ) ,
147+ userId : userId ,
148+ } : {
143149 workspaceId : workspace . _id . toString ( ) ,
144150 userId : userId ,
145151 tariffPlanId : tariffPlan . _id . toString ( ) ,
146152 shouldSaveCard : shouldSaveCard === 'true' ,
147- isCardLinkOperation : isCardLinkOperation === 'true' ,
148- } ) ;
153+ }
154+
155+ checksum = await checksumService . generateChecksum ( checksumData ) ;
149156 } catch ( e ) {
150157 const error = e as Error ;
151158
@@ -161,11 +168,24 @@ export default class CloudPaymentsWebhooks {
161168 name : tariffPlan . name ,
162169 monthlyCharge : tariffPlan . monthlyCharge ,
163170 } ,
171+ isCardLinkOperation,
164172 currency : 'RUB' ,
165173 checksum,
166174 } ) ;
167175 }
168176
177+ /**
178+ * Returns true if workspace's plan is expired
179+ * @param workspace - workspace to check
180+ */
181+ private isPlanExpired ( workspace : WorkspaceModel ) : boolean {
182+ const lastChargeDate = new Date ( workspace . lastChargeDate ) ;
183+ const planExpiracyDate = lastChargeDate . setMonth ( lastChargeDate . getMonth ( ) + 1 ) ;
184+ const isPlanExpired = planExpiracyDate < Date . now ( ) ;
185+
186+ return isPlanExpired ;
187+ }
188+
169189 /**
170190 * Generates invoice id for payment
171191 *
@@ -204,7 +224,13 @@ export default class CloudPaymentsWebhooks {
204224 let member : ConfirmedMemberDBScheme ;
205225 let plan : PlanDBScheme ;
206226
207- if ( ! data . workspaceId || ! data . tariffPlanId || ! data . userId || data . isCardLinkOperation === undefined ) {
227+ if ( data . isCardLinkOperation && ( ! data . userId || ! data . workspaceId ) ) {
228+ this . sendError ( res , CheckCodes . PAYMENT_COULD_NOT_BE_ACCEPTED , '[Billing / Check] Card linking – invalid data' , body ) ;
229+
230+ return ;
231+ }
232+
233+ if ( ! data . isCardLinkOperation && ( ! data . userId || ! data . workspaceId || ! data . tariffPlanId ) ) {
208234 this . sendError ( res , CheckCodes . PAYMENT_COULD_NOT_BE_ACCEPTED , '[Billing / Check] There is no necessary data in the request' , body ) ;
209235
210236 return ;
0 commit comments