import assert from 'assert'; import Offline from './Offline'; import Account from './Account'; import WechatPay from './WechatPay'; import { registerAccountEntity } from '../../checkers/abstractChecker'; const PayChannelDict = {}; const PayClazzEntityDict = { 'account': { accountEntity: '', clazzConstructor: async () => new Account(), }, 'offlineAccount': { accountEntity: 'offlineAccount', clazzConstructor: async (applicationId, entityId, context) => { const [offlineAccount] = await context.select('offlineAccount', { data: { id: 1, type: 1, channel: 1, name: 1, qrCode: 1, taxLossRatio: 1, refundCompensateRatio: 1, refundGapDays: 1, allowDeposit: 1, allowPay: 1, systemId: 1, price: 1, enabled: 1, allowWithdrawTransfer: 1, withdrawTransferLossRatio: 1, }, filter: { id: entityId, }, }, { dontCollect: true }); assert(offlineAccount.enabled); return new Offline(offlineAccount); } }, 'wpProduct': { accountEntity: 'wpAccount', clazzConstructor: async (applicationId, entityId, context) => { const [[wpProduct], [application]] = await Promise.all([ context.select('wpProduct', { data: { id: 1, type: 1, taxLossRatio: 1, enabled: 1, wpAccount: { id: 1, mchId: 1, taxLossRatio: 1, refundGapDays: 1, refundCompensateRatio: 1, publicKeyFilePath: 1, privateKeyFilePath: 1, apiV3Key: 1, wechatPay: { id: 1, payNotifyUrl: 1, refundNotifyUrl: 1, }, enabled: 1, } }, filter: { id: entityId, } }, { dontCollect: true }), context.select('application', { data: { id: 1, type: 1, config: 1, }, filter: { id: applicationId, }, }, { dontCollect: true }) ]); const { type, config } = application; assert(wpProduct.enabled && wpProduct.wpAccount?.enabled); switch (type) { case 'web': { const { wechat } = config; assert(wechat); const appId = wechat.appId; return new WechatPay(wpProduct, appId); } case 'wechatMp': { const { appId } = config; return new WechatPay(wpProduct, appId); } case 'wechatPublic': { const { appId } = config; return new WechatPay(wpProduct, appId); } default: { assert(false, '暂时不支持'); } } } }, }; // 这里用一个flag来表达先后顺序,如果有registerPayClazzEntity,框架应保证register在get之前 // 目前因为没有registerPayClazzEntity,所以没测,可能不对。by Xc 20240608 let MODULE_USED = false; export function registerPayClazzEntity(entity, def, schema) { if (!MODULE_USED) { assert(!MODULE_USED); } PayClazzEntityDict[entity] = { accountEntity: def.accountEntity, clazzConstructor: def.clazzConstructor, }; // 检查此entity是否符合注册要求 const { attributes } = schema[entity]; const { attributes: payAttr } = schema.pay; const { attributes: accountAttr } = schema[def.accountEntity]; assert(payAttr.entity.enumeration?.includes(entity)); assert(accountAttr.price && accountAttr.price.type === 'decimal'); assert(accountAttr.systemId && accountAttr.systemId.type === 'ref' && accountAttr.systemId.ref === 'system'); registerAccountEntity(def.accountEntity); } export async function getPayClazz(applicationId, entity, entityId, context) { if (!MODULE_USED) { assert(!MODULE_USED); } const key = entity === 'account' ? entity : `${entity}.${entityId}`; if (PayChannelDict.hasOwnProperty(key)) { return PayChannelDict[key]; } const PayClazz = await PayClazzEntityDict[entity].clazzConstructor(applicationId, entityId, context); PayChannelDict[key] = PayClazz; return PayClazz; }