All files / src/modules/billing click.signing.service.ts

100% Statements 16/16
70% Branches 7/10
100% Functions 4/4
100% Lines 14/14

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 5012x 12x 12x     3x 3x 3x       12x 12x                     1x 1x     1x                         2x 2x     2x          
import { Injectable } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { createHash, timingSafeEqual as nodeTimingSafeEqual } from 'crypto';
 
function safeEqual(a: string, b: string): boolean {
  const A = Buffer.from(a, 'utf8');
  const B = Buffer.from(b, 'utf8');
  return A.length === B.length && nodeTimingSafeEqual(A, B);
}
 
@Injectable()
export class ClickSigningService {
  constructor(private readonly config: ConfigService) {}
 
  verifyPrepareSig(p: {
    click_trans_id: string;
    service_id: number;
    merchant_trans_id: string;
    amount: number;
    action: number;
    sign_time: string;
    sign_string: string;
  }): boolean {
    const secret = this.config.get<string>('CLICK_SECRET_KEY') || '';
    const expected = createHash('md5')
      .update(`${p.click_trans_id}${p.service_id}${secret}${p.merchant_trans_id}${p.amount}${p.action}${p.sign_time}`)
      .digest('hex');
    return safeEqual(expected, p.sign_string);
  }
 
  verifyCompleteSig(p: {
    click_trans_id: string;
    service_id: number;
    merchant_trans_id: string;
    merchant_prepare_id: number;
    amount: number;
    action: number;
    sign_time: string;
    sign_string: string;
  }): boolean {
    const secret = this.config.get<string>('CLICK_SECRET_KEY') || '';
    const expected = createHash('md5')
      .update(`${p.click_trans_id}${p.service_id}${secret}${p.merchant_trans_id}${p.merchant_prepare_id}${p.amount}${p.action}${p.sign_time}`)
      .digest('hex');
    return safeEqual(expected, p.sign_string);
  }
}