瀏覽代碼

开放KYC提交接口

test 7 月之前
父節點
當前提交
7c875e4b63
共有 3 個文件被更改,包括 239 次插入4 次删除
  1. 23 0
      src/modules/dj/controller/admin/open.ts
  2. 9 4
      src/modules/dj/service/kyc.ts
  3. 207 0
      src/modules/dj/service/openKyc.ts

+ 23 - 0
src/modules/dj/controller/admin/open.ts

@@ -27,6 +27,7 @@ import { WithdrawService } from '../../service/withdraw';
 import { KycService } from '../../service/kyc';
 import { RepayService } from '../../service/repay';
 import { WhiteIpMiddleware } from '../../middleware/whiteIp';
+import { KycOpenService } from '../../service/openKyc';
 
 @Provide()
 @CoolController()
@@ -52,6 +53,9 @@ export class PayOpenController extends BaseController {
 
   @Inject()
   kycService: KycService;
+  
+  @Inject()
+  kycOpenService: KycOpenService;
 
   @Inject()
   repayService: RepayService
@@ -168,4 +172,23 @@ export class PayOpenController extends BaseController {
   public async kycToPay(@Body(ALL) payload: any) {
     return this.ok(await this.kycService.toPay(payload));
   }
+
+  @CoolTag(TagTypes.IGNORE_TOKEN)
+  @Post('/kyc/toBaisc', { summary: 'kyc basic 保存' })
+  public async submitBaisc(@Body(ALL) payload: any) {
+    return this.ok(await this.kycOpenService.createOpenBasic(payload));
+  }
+
+  @CoolTag(TagTypes.IGNORE_TOKEN)
+  @Post('/kyc/toAdvanced', { summary: 'kyc advanced 保存' })
+  public async submitAdvanced(@Files() files, @Fields() fields) {
+    return this.ok(await this.kycOpenService.createOpenAdvanced(fields, files));
+  }
+
+  @CoolTag(TagTypes.IGNORE_TOKEN)
+  @Post('/kyc/toPremium', { summary: 'kyc basic 保存' })
+  public async submitPremium(@Files() files, @Fields() fields) {
+    console.log(files, fields)
+    return this.ok(await this.kycOpenService.createOpenPremium(fields, files));
+  }
 }

+ 9 - 4
src/modules/dj/service/kyc.ts

@@ -10,8 +10,6 @@ import * as md5 from 'md5';
 
 @Provide()
 export class KycService extends BaseService {
-
-
   @InjectEntityModel(KycEntity)
   kycEntity: Repository<KycEntity>;
 
@@ -28,7 +26,7 @@ export class KycService extends BaseService {
     if (!orderNo || !order) {
       throw new CoolCommException('Order does not exist');
     }
-    if(!customer) {
+    if (!customer) {
       throw new CoolCommException('Customer does not exist');
     }
     if (order.payUrl) {
@@ -114,7 +112,8 @@ export class KycService extends BaseService {
       outUserId,
       level: 1,
       levelEnd: 3,
-      customerId: ''
+      customerId: '',
+      payUrl: ''
     }
     const kyc = await this.kycEntity.findOneBy({
       userId: order.userId,
@@ -140,6 +139,12 @@ export class KycService extends BaseService {
     }
     const monthly = await this.getMonthlyLevel(order);
     data.levelEnd = Math.max(dailyLevel, weekly, monthly);
+    if (data.level > data.levelEnd && data.customerId) {
+      const { payUrl } = await this.toPay({
+        orderNo: orderNo, customerId: data.customerId
+      });
+      data.payUrl = payUrl;
+    }
     return data;
   }
 

+ 207 - 0
src/modules/dj/service/openKyc.ts

@@ -0,0 +1,207 @@
+import { Inject, Logger, Provide } from '@midwayjs/decorator';
+import { BaseService, CoolCommException } from '@cool-midway/core';
+import { InjectEntityModel } from '@midwayjs/typeorm';
+import { Repository } from 'typeorm';
+import * as _ from 'lodash';
+import { KycEntity } from '../entity/kyc';
+import { SunPayService } from './channels/sunpay';
+import { ILogger } from '@midwayjs/logger';
+import { PayService } from './pay';
+import * as moment from 'moment';
+import * as md5 from 'md5';
+
+@Provide()
+export class KycOpenService extends BaseService {
+  @InjectEntityModel(KycEntity)
+  kycEntity: Repository<KycEntity>;
+
+  @Inject()
+  sunPayService: SunPayService
+
+  @Inject()
+  payService: PayService
+
+  @Logger()
+  logger: ILogger;
+
+  async validPremiumParam(payload, files) {
+    if (_.isEmpty(payload.mchId)) {
+      throw new Error('商户编号【mchId】不能为空');
+    }
+    if (_.isEmpty(payload.kycUserId)) {
+      throw new Error('KYC用户ID【kycUserId】不能为空');
+    }
+    if (!files.residentialAddress) {
+      throw new Error('居住地址证明文件【residentialAddress】不能为空');
+    }
+    if (!files.income) {
+      throw new Error('收入证明文件【income】不能为空');
+    }
+    if (_.isEmpty(payload.sign)) {
+      throw new Error('签名【sign】不能为空');
+    }
+  }
+
+  async createOpenPremium(payload, files) {
+    try {
+      this.logger.info('KYC高级认证', JSON.stringify(payload));
+      if(!files) {
+        throw new Error('参数错误,请提交正确参数');
+      }
+      const fileObj = {};
+      files.forEach(item => {
+        fileObj[item.fieldName] = item
+      })
+      await this.validPremiumParam(payload, fileObj);
+      const merchant = await this.payService.validMerchant(payload.mchId);
+      await this.payService.validSign(payload, merchant);
+      const kyc = await this.kycEntity.findOneBy({ kycUserId: payload.kycUserId });
+      if (!kyc.customerId || !kyc) {
+        throw new CoolCommException('KYC user does not exist');
+      }
+      const data = await this.sunPayService.createPremium({
+        customerId: kyc.customerId,
+      }, fileObj);
+      await this.kycEntity.update(kyc.id, { level: '3' });
+      return { kycUserId: payload.kycUserId }
+    } catch (err) {
+      this.logger.error('KYC高级认证提交失败', JSON.stringify(payload), err.message);
+      throw new CoolCommException(err.message);
+    }
+  }
+
+  async validAdvanced(payload, files) {
+    if (_.isEmpty(payload.mchId)) {
+      throw new Error('商户编号【mchId】不能为空');
+    }
+    if (_.isEmpty(payload.kycUserId)) {
+      throw new Error('KYC用户ID【kycUserId】不能为空');
+    }
+    if (_.isEmpty(payload.documentType)) {
+      throw new Error('证件类型【documentType】不能为空');
+    }
+    if (+payload.documentType < 0 || +payload.documentType > 2) {
+      throw new Error('证件类型【documentType】取值错误');
+    }
+    if (_.isEmpty(payload.documentNumber)) {
+      throw new Error('证件号码【documentNumber】不能为空');
+    }
+    if (!files.frontSideDocument) {
+      throw new Error('证件正面图片【frontSideDocument】不能为空');
+    }
+    if (!files.backSideDocument) {
+      throw new Error('证件背面图片【backSideDocument】不能为空');
+    }
+    if (!files.customerPhoto) {
+      throw new Error('客户人像图片【customerPhoto】不能为空');
+    }
+    if (_.isEmpty(payload.sign)) {
+      throw new Error('签名【sign】不能为空');
+    }
+  }
+
+  async createOpenAdvanced(payload, files) {
+    try {
+      this.logger.info('KYC进阶认证', JSON.stringify(payload));
+      if(!files) {
+        throw new Error('参数错误,请提交正确参数');
+      }
+      const fileObj = {};
+      files.forEach(item => {
+        fileObj[item.fieldName] = item
+      })
+      await this.validAdvanced(payload, fileObj);
+      const merchant = await this.payService.validMerchant(payload.mchId);
+      await this.payService.validSign(payload, merchant);
+
+      const kyc = await this.kycEntity.findOneBy({ kycUserId: payload.kycUserId });
+      if (!kyc.customerId || !kyc) {
+        throw new CoolCommException('KYC user does not exist');
+      }
+      const data = await this.sunPayService.createAdvanced({
+        customerId: kyc.customerId,
+        documentType: payload.documentType,
+        documentNumber: payload.documentNumber
+      }, fileObj);
+      await this.kycEntity.update(kyc.id, { level: '2' });
+      return { kycUserId: payload.kycUserId }
+    } catch (err) {
+      this.logger.error('KYC进阶认证提交失败', JSON.stringify(payload), err.message);
+      throw new CoolCommException(err.message);
+    }
+  }
+
+  async validBasicParam(payload) {
+    if (_.isEmpty(payload.mchId)) {
+      throw new Error('商户编号【mchId】不能为空');
+    }
+    if (_.isEmpty(payload.userId)) {
+      throw new Error('商户平台用户ID【userId】不能为空');
+    }
+    if (_.isEmpty(payload.customerName)) {
+      throw new Error('客户姓名【customerName】不能为空');
+    }
+    if (_.isEmpty(payload.customerEmail)) {
+      throw new Error('客户邮箱地址【customerEmail】不能为空');
+    }
+    if (_.isEmpty(payload.countryCode)) {
+      throw new Error('国家编码【countryCode】不能为空');
+    }
+    if (_.isEmpty(payload.residenceCountry)) {
+      throw new Error('国家编码【residenceCountry】不能为空');
+    }
+    if (_.isEmpty(payload.birthDate)) {
+      throw new Error('出生日期【birthDate】不能为空');
+    }
+    if (!moment(payload.birthDate).isValid()) {
+      throw new Error('出生日期【birthDate】非正确日期格式');
+    }
+    if (_.isEmpty(payload.sign)) {
+      throw new Error('签名【sign】不能为空');
+    }
+  }
+
+  async createOpenBasic(payload) {
+    try {
+      this.logger.info('KYC基础认证', JSON.stringify(payload));
+      await this.validBasicParam(payload);
+      const merchant = await this.payService.validMerchant(payload.mchId);
+      await this.payService.validSign(payload, merchant);
+      const kyc = await this.kycEntity.findOneBy({
+        mchId: payload.mchId,
+        userId: payload.userId,
+        code: 'SUN_CARD',
+      })
+      if (kyc) {
+        throw new Error('当前客户ID已存在,请勿重复提交');
+      }
+      const outUserId = md5(payload.mchId + '_' + payload.userId + 'v2');
+      const { customerId } = await this.sunPayService.createBasic({
+        outUserId,
+        customerName: payload.customerName,
+        customerEmail: payload.customerEmail,
+        countryCode: payload.countryCode,
+        residenceCountry: payload.residenceCountry,
+        birthDate: payload.birthDate,
+      });
+      if (customerId) {
+        await this.kycEntity.insert({
+          userId: payload.userId,
+          mchId: payload.mchId,
+          code: 'SUN_CARD',
+          kycUserId: outUserId,
+          customerId: customerId,
+          level: '1',
+          country: payload.countryCode
+        })
+        return { kycUserId: outUserId }
+      } else {
+        throw new CoolCommException('Network exception, please try again later');
+      }
+
+    } catch (err) {
+      this.logger.error('KYC基础认证提交失败', JSON.stringify(payload), err.message);
+      throw new CoolCommException(err.message);
+    }
+  }
+}