Jelajahi Sumber

feat: 换汇手续费 3-11

max 4 bulan lalu
induk
melakukan
d2ac125315
1 mengubah file dengan 298 tambahan dan 178 penghapusan
  1. 298 178
      src/modules/api/service/webhook.ts

+ 298 - 178
src/modules/api/service/webhook.ts

@@ -1,17 +1,21 @@
-import {BaseService} from '@cool-midway/core';
-import {ILogger, Provide} from '@midwayjs/core';
-import {Inject} from '@midwayjs/decorator';
-import {InjectEntityModel} from '@midwayjs/typeorm';
-import {Repository} from 'typeorm';
-import {CustomerEntity} from '../../payment/entity/customer';
-import {PaymentService} from '../../payment/service/payment';
-import {PayeeEntity} from '../../payment/entity/payee';
-import {SunPayAdapter} from '../../payment/adapter/sunpay.adapter';
-import {OpenPaymentOrderEntity, OrderType,} from '../entity/open_payment_order';
-import {WithdrawChannelEntity} from '../entity/withdrawChannel';
-import {OpenAccountEntity} from '../entity/open_account';
-import {EasyPayAdapter} from '../../payment/adapter/easypay.adapter';
+import { BaseService } from '@cool-midway/core';
+import { ILogger, Provide } from '@midwayjs/core';
+import { Inject } from '@midwayjs/decorator';
+import { InjectEntityModel } from '@midwayjs/typeorm';
+import { Repository } from 'typeorm';
+import { CustomerEntity } from '../../payment/entity/customer';
+import { PaymentService } from '../../payment/service/payment';
+import { PayeeEntity } from '../../payment/entity/payee';
+import { SunPayAdapter } from '../../payment/adapter/sunpay.adapter';
+import {
+  OpenPaymentOrderEntity,
+  OrderType,
+} from '../entity/open_payment_order';
+import { WithdrawChannelEntity } from '../entity/withdrawChannel';
+import { OpenAccountEntity } from '../entity/open_account';
+import { EasyPayAdapter } from '../../payment/adapter/easypay.adapter';
 import * as md5 from 'md5';
+import { OpenUserEntity } from '../entity/open_user';
 
 /**
  * 描述
@@ -21,6 +25,9 @@ export class OpenApiWebhookService extends BaseService {
   @InjectEntityModel(PayeeEntity)
   payeeEntity: Repository<PayeeEntity>;
 
+  @InjectEntityModel(OpenUserEntity)
+  openUserEntity: Repository<OpenUserEntity>;
+
   @InjectEntityModel(CustomerEntity)
   customerEntity: Repository<CustomerEntity>;
 
@@ -49,73 +56,69 @@ export class OpenApiWebhookService extends BaseService {
   logger: ILogger;
 
   async easypayWebhook(params, type: string) {
-    if (type !== 'notification') {
-      this.ctx.status = 400;
-      this.ctx.body = {};
-      return;
-    }
-    await this.waitByTime(2200);
     try {
       this.logger.info(
         `easypay的webhook_${type}: params${JSON.stringify(params)}`
       );
       // TODO 各类回调处理 后续处理
-      // 账户审核通过   account_approved
-      // 账户审核驳回   account_rejected
-      // 实名待更新     legal_entity_request_created
-      // 实名更新审核通过 legal_entity_request_success
-      // 实名更新审核驳回 legal_entity_request_rejected
-      // 收款账户申请成功 application_success
-      // 收款账户申请失败 application_failed
-      // 收款账户已下发   bank_account_created
-      // 收款账户信息变更 bank_account_updated
-      // 收单支付成功通知 acquiring_payment_success
-      // 收单支付成功通知 acquiring_refund_success
-      // 收单退款失败通知 acquiring_refund_failed
-      // 换汇失败       exchange_failed
-      // 付款失败       payment_failed
-      // 付款银行退回    payment_refunded
-      // 转账失败        transfer_failed
 
       //  const {type} = params
       switch (params.type) {
+        case 'account_approved':
+          // 账户审核通过   account_approved
+          break;
+        case 'account_rejected':
+          // 账户审核驳回   account_rejected
+          break;
+        case 'legal_entity_request_created':
+          // 实名待更新     legal_entity_request_created
+          break;
+        case 'legal_entity_request_success':
+          // 实名更新审核通过 legal_entity_request_success
+          break;
+        case 'legal_entity_request_rejected':
+          // 实名更新审核驳回 legal_entity_request_rejected
+          break;
+        case 'application_success':
+          // 收款账户申请成功 application_success
+          break;
+        case 'application_failed':
+          // 收款账户申请失败 application_failed
+          break;
+        case 'bank_account_created':
+          // 收款账户已下发   bank_account_created
+          break;
+        case 'bank_account_updated':
+          // 收款账户信息变更 bank_account_updated
+          break;
+        case 'acquiring_payment_success':
+          // 收单支付成功通知 acquiring_payment_success
+          break;
+        case 'acquiring_refund_success':
+          // 收单支付成功通知 acquiring_refund_success
+          break;
+        case 'acquiring_refund_failed':
+          // 收单退款失败通知 acquiring_refund_failed
+          break;
+        case 'exchange_failed':
+          // 换汇失败       exchange_failed
+          break;
+        case 'payment_failed':
+          // 付款失败       payment_failed
+          break;
+        case 'payment_refunded':
+          // 付款银行退回    payment_refunded
+          break;
+        case 'transfer_failed':
+          // 付款银行退回    transfer_failed
+          break;
         case 'deposit_success':
           // 入账成功       deposit_success
           return this.deposit_success(params);
-          break;
         case 'exchange_success':
           // 换汇成功       exchange_success
           // 如果换汇成功,则收取手续费
-          /*
-          params
-          {
-            "type": "exchange_success",
-            "data": {
-                "id": "13ea4d84b92a4070b55dfafadcafcca3",
-                "order_no": "20250310161942842514",
-                "request_id": null,
-                "reference": null,
-                "account_id": "2bd64372841a54bf8b41f879ff07884b",
-                "sell_currency": "USD",
-                "sell_amount": 2577,
-                "exchange_rate": 0.776169,
-                "buy_amount": 2000,
-                "buy_currency": "GBP",
-                "reason": null,
-                "create_time": "2025-03-10T16:19:42+08:00",
-                "update_time": "2025-03-10T16:20:11+08:00",
-                "completed_time": "2025-03-10T16:20:11+08:00",
-                "status": "SUCCESS",
-                "details_url": null,
-                "detail_status": null,
-                "details_reason": [
-
-                ]
-            }
-          }
-          */
-
-          break;
+          return this.exchange_success(params);
         case 'payment_success':
           // 付款成功       payment_success
           // 如果付款成功,则收取手续费
@@ -152,6 +155,8 @@ export class OpenApiWebhookService extends BaseService {
 
           break;
         case 'transfer_success':
+          // 转账延迟2.2秒处理
+          await this.waitByTime(2200);
           // 转账成功       transfer_success
           // 如果付款成功,则收取手续费
           /*
@@ -183,7 +188,9 @@ export class OpenApiWebhookService extends BaseService {
         `easypay的webhook error ${type}: params${JSON.stringify(params)}`
       );
     }
-    this.ctx.status = 200;
+    // 转账延迟4秒处理
+    await this.waitByTime(4000);
+    this.ctx.status = 400;
     this.ctx.body = {};
     return;
   }
@@ -197,106 +204,10 @@ export class OpenApiWebhookService extends BaseService {
     });
   }
 
-  //
+  // 入账成功 的手续费处理
   async deposit_success(params) {
-    // 如果入账成功,则收取手续费
-    console.log(193, params);
-
-    // 获取回调用户的详情
-    const accountInfo = await this.getAccountInfo(params.data.account_id);
-    if (!accountInfo) {
-      // TODO 如果不存在的话,则为白标用户
-      this.ctx.status = 400;
-      this.ctx.body = {};
-      return;
-    }
-
-    // 获取费率信息
-    const withdrawChannelFee = await this.getWithdrawChannelFee({
-      account_id: params.data.account_id,
-      currency: params.data.currency,
-      order_type: 'DEPOSIT',
-      channel: 'EASYPAY',
-      amount: params.data.amount,
-      mch_id: accountInfo.mch_id,
-    });
-    // 查询用户的资金
-
-    // 记录入账流水
-    await this.openPaymentOrderEntity.insert({
-      mch_id: accountInfo.mch_id,
-      amount: params.data.amount/100,
-      account_id: params.data.account_id,
-      to_account_id: params.data.account_id,
-      event_id: params.data.id,
-      currency: params.data.currency,
-      status: params.data.status,
-      order_type: OrderType.DEPOSIT,
-      payment_type: params.data.payment_type,
-      order_id: params.data.order_no,
-      fee: withdrawChannelFee,
-      additional_info: {}
-    });
-    this.logger.info(
-      `记录入账流水, ${JSON.stringify({
-        mch_id: accountInfo.mch_id,
-        amount: params.data.amount/100,
-        account_id: params.data.account_id,
-        to_account_id: params.data.account_id,
-        event_id: params.data.id,
-        currency: params.data.currency,
-        status: params.data.status,
-        order_type: OrderType.DEPOSIT,
-        payment_type: params.data.payment_type,
-        order_id: params.data.order_no,
-        fee: withdrawChannelFee,
-      })}`
-    );
-    // 收取手续费: 转账
-    // /v1/transfers
-    const transfers_params = {
-      // ...openOrderObj,
-      request_id: md5(`${accountInfo.mch_id}_${params.data.id}`),
-      from_account_id: params.data.account_id,
-      to_account_id: this.easyPayAdapter.baseInfo.account_id,
-      currency: params.data.currency,
-      amount: withdrawChannelFee*100,
-      purpose: '收取手续费用',
-    };
-    this.logger.info(`记录入账流水的费率, ${JSON.stringify(transfers_params)}`);
-    // 截取流水的转账
-    const res = await this.easyPayAdapter.request(
-      'POST',
-      '/v1/transfers',
-      transfers_params
-    );
-    // 记录入账手续费
-    await this.openPaymentOrderEntity.insert({
-      request_id: transfers_params.request_id,
-      mch_id: accountInfo.mch_id,
-      amount: withdrawChannelFee,
-      account_id: params.data.account_id,
-      from_account_id: params.data.account_id,
-      to_account_id: this.easyPayAdapter.baseInfo.account_id,
-      event_id: params.data.id,
-      currency: params.data.currency,
-      status: params.data.status,
-      order_type: OrderType.TRANSACTION_FEE_ORDER,
-      payment_type: params.data.payment_type,
-      order_id: params.data.order_no,
-      fee: 0,
-      additional_info: {}
-    });
-    this.ctx.status = 200;
-    this.ctx.body = {};
-    return;
-
-    // 转账的流水
-
-    // withdrawChannelFee
-    // withdrawChannel
-
-    /*
+    try {
+      /*
     2025-03-11 16:58:09.069 INFO 113849 [-/::ffff:127.0.0.1/-/1ms POST /api/open/easypay-webhook/notification] easypay的webhook_notification: params{"type":"deposit_success","data":{"id":"85a2e73b90d94354b14b925c8e23b876","bank_account_id":"7021a5e645574004b5678213f94df8a5","order_no":"20250311165807046795","account_id":"590f080eb299590385c7aa628274e73c","bic_number":null,"account_number":"79765000168","inward_amount":90000,"fee":0,"amount":90000,"currency":"EUR","payer":"付款信息 格式:{sender.name};{sender.address};{sender.country};{sender.account_number} or {sender.iban};{sender.bic};{sender.routing_code};附言","comment":"附言","payment_type":"SWIFT","order_type":"DEPOSIT","payment_id":null,"clearing_system":null,"status":"SUCCESS","create_time":"2025-03-11T16:58:08+08:00","update_time":"2025-03-11T16:58:08+08:00","completed_time":"2025-03-11T16:58:08+08:00"}}
 
     {
@@ -325,24 +236,234 @@ export class OpenApiWebhookService extends BaseService {
       }
     }
     */
-    //
-    if (params.data.status === 'SUCCESS') {
-      // 收取手续费
-      // 记录流水
-      //
-      // this.openPaymentOrderEntity.insert({
-      //   mch_id
-      // })
+      // 获取回调用户的详情
+      const accountInfo = await this.getAccountInfo(params.data.account_id);
+      if (!accountInfo) {
+        // TODO 如果不存在的话,则为白标用户
+        // 转账延迟4秒处理
+        await this.waitByTime(4000);
+        this.ctx.status = 400;
+        this.ctx.body = {};
+        return;
+      }
+
+      // 获取费率信息
+      const withdrawChannelFee = await this.getWithdrawChannelFee({
+        account_id: params.data.account_id,
+        currency: params.data.currency,
+        order_type: 'DEPOSIT',
+        channel: 'EASYPAY',
+        amount: params.data.amount,
+        mch_id: accountInfo.mch_id,
+      });
+      // 查询用户的资金
+
+      // 记录入账流水
+      const openPaymentOrderParams = {
+        mch_id: accountInfo.mch_id,
+        amount: params.data.amount / 100,
+        account_id: params.data.account_id,
+        from_account_id: params.data.account_id,
+        to_account_id: params.data.account_id,
+        event_id: params.data.id,
+        currency: params.data.currency,
+        status: params.data.status,
+        order_type: OrderType.DEPOSIT,
+        payment_type: params.data.payment_type,
+        order_id: params.data.order_no,
+        fee: withdrawChannelFee,
+        additional_info: {},
+      };
+      await this.openPaymentOrderEntity.insert(openPaymentOrderParams);
+      this.logger.info(
+        `记录入账流水, ${JSON.stringify(openPaymentOrderParams)}`
+      );
+      // 收取手续费: 转账
+      // /v1/transfers
+      const transfers_params = {
+        // ...openOrderObj,
+        request_id: md5(`${accountInfo.mch_id}_${params.data.id}`),
+        from_account_id: params.data.account_id,
+        to_account_id: this.easyPayAdapter.baseInfo.account_id,
+        currency: params.data.currency,
+        amount: withdrawChannelFee * 100,
+        purpose: '收取手续费用',
+      };
+      this.logger.info(
+        `记录入账流水的费率, ${JSON.stringify(transfers_params)}`
+      );
+      // 截取流水的转账
+      const res = await this.easyPayAdapter.request(
+        'POST',
+        '/v1/transfers',
+        transfers_params
+      );
+      // 记录入账手续费的流水
+      await this.openPaymentOrderEntity.insert({
+        request_id: transfers_params.request_id,
+        mch_id: accountInfo.mch_id,
+        amount: withdrawChannelFee,
+        account_id: params.data.account_id,
+        from_account_id: params.data.account_id,
+        to_account_id: this.easyPayAdapter.baseInfo.account_id,
+        event_id: params.data.id,
+        currency: params.data.currency,
+        status: params.data.status,
+        order_type: OrderType.TRANSACTION_FEE_ORDER,
+        payment_type: params.data.payment_type,
+        order_id: res.data.order_no, // 这里是转账的订单编号
+        fee: 0,
+        additional_info: {},
+      });
+      this.ctx.status = 200;
+      this.ctx.body = {};
+      return;
+    } catch (error) {
+      this.logger.error(`记录入账流水失败, ${JSON.stringify(params)}`);
+      this.logger.error(error);
+    }
+  }
+
+  // 换汇成功的回调
+  async exchange_success(params) {
+    try {
+      /*
+        params
+        {
+          "type": "exchange_success",
+          "data": {
+              "id": "13ea4d84b92a4070b55dfafadcafcca3",
+              "order_no": "20250310161942842514",
+              "request_id": null,
+              "reference": null,
+              "account_id": "2bd64372841a54bf8b41f879ff07884b",
+              "sell_currency": "USD",
+              "sell_amount": 2577,
+              "exchange_rate": 0.776169,
+              "buy_amount": 2000,
+              "buy_currency": "GBP",
+              "reason": null,
+              "create_time": "2025-03-10T16:19:42+08:00",
+              "update_time": "2025-03-10T16:20:11+08:00",
+              "completed_time": "2025-03-10T16:20:11+08:00",
+              "status": "SUCCESS",
+              "details_url": null,
+              "detail_status": null,
+              "details_reason": [
+              ]
+          }
+        }
+      */
+
+      // 获取回调用户的详情
+      const accountInfo = await this.getAccountInfo(params.data.account_id);
+      if (!accountInfo) {
+        // TODO 如果不存在的话,暂时不处理
+        // 转账延迟4秒处理
+        await this.waitByTime(4000);
+        this.ctx.status = 400;
+        this.ctx.body = {};
+        return;
+      }
+
+      // 获取费率信息
+      const withdrawChannelFee = await this.getWithdrawChannelFee({
+        account_id: params.data.account_id,
+        currency: params.data.buy_currency,
+        order_type: 'EXCHANGE',
+        channel: 'EASYPAY',
+        amount: params.data.buy_amount,
+        mch_id: accountInfo.mch_id,
+      });
+
+      // 记录入账流水
+      const openPaymentOrderParams = {
+        mch_id: accountInfo.mch_id,
+        account_id: params.data.account_id,
+        from_account_id: params.data.account_id,
+        to_account_id: params.data.account_id,
+        event_id: params.data.id,
+        currency: params.data.sell_currency,
+        amount: params.data.sell_amount / 100,
+        target_currency: params.data.buy_currency,
+        target_amount: params.data.buy_amount / 100,
+        status: params.data.status,
+        order_type: OrderType.EXCHANGE,
+        payment_type: params.data.payment_type,
+        order_id: params.data.order_no,
+        fee: withdrawChannelFee,
+        additional_info: {},
+      };
+      await this.openPaymentOrderEntity.insert(openPaymentOrderParams);
+      this.logger.info(
+        `记录换汇流水, ${JSON.stringify(openPaymentOrderParams)}`
+      );
+
+      // 收取手续费: 换汇
+      // /v1/transfers
+      const transfers_params = {
+        request_id: md5(`${accountInfo.mch_id}_${params.data.id}`),
+        from_account_id: params.data.account_id,
+        to_account_id: this.easyPayAdapter.baseInfo.account_id,
+        currency: params.data.buy_currency, // 收取买入的币种费用
+        target_amount: params.data.buy_amount / 100,
+        amount: withdrawChannelFee * 100, // 分
+        purpose: '收取手续费用',
+      };
+      this.logger.info(
+        `记录入账流水的费率, ${JSON.stringify(transfers_params)}`
+      );
+      // 截取流水的转账
+      const res = await this.easyPayAdapter.request(
+        'POST',
+        '/v1/transfers',
+        transfers_params
+      );
+      // 记录入账手续费的流水
+      await this.openPaymentOrderEntity.insert({
+        request_id: transfers_params.request_id,
+        mch_id: accountInfo.mch_id,
+        amount: withdrawChannelFee,
+        account_id: params.data.account_id,
+        from_account_id: params.data.account_id,
+        to_account_id: this.easyPayAdapter.baseInfo.account_id,
+        event_id: params.data.id,
+        currency: transfers_params.currency,
+        status: params.data.status,
+        order_type: OrderType.TRANSACTION_FEE_ORDER,
+        payment_type: params.data.payment_type,
+        order_id: res.data.order_no, // 这里是转账的订单编号
+        fee: 0,
+        additional_info: {},
+      });
+      this.ctx.status = 200;
+      this.ctx.body = {};
+      return;
+    } catch (error) {
+      this.logger.error(`记录换汇流水失败, ${JSON.stringify(params)}`);
+      this.logger.error(error);
     }
   }
 
-  //
+  // 如果查询都是空的延迟处理
   async getAccountInfo(account_id) {
-    return await this.openAccountEntity.findOne({
+    const openAccount = await this.openAccountEntity.findOne({
       where: {
         account_id,
       },
     });
+    if(openAccount) {
+      return openAccount
+    }
+    const openUser = await this.openUserEntity.findOne({
+      where: {
+        account_id,
+      },
+    });
+    if(openUser) {
+      return openUser
+    }
+    return null
   }
 
   async getWithdrawChannelFee({
@@ -363,9 +484,8 @@ export class OpenApiWebhookService extends BaseService {
         status: 1,
       },
     });
-    console.log(360, withdrawChannel);
     // 费率
-    const fee = (Number.parseInt(withdrawChannel.rate) / 100) * (amount/100); // 费率费用
+    const fee = (Number.parseInt(withdrawChannel.rate) / 100) * (amount / 100); // 费率费用
     // 单笔固定费用
     const basicFee = withdrawChannel.basicFee;
     // 单笔最低费用