oak-pay-business/es/utils/payClazz/index.js

152 lines
5.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 (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 (entityId, context) => {
const [wpProduct] = await context.select('wpProduct', {
data: {
id: 1,
type: 1,
taxLossRatio: 1,
refundCompensateRatio: 1,
refundGapDays: 1,
needReceiving: 1,
enabled: 1,
application: {
id: 1,
config: 1,
type: 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 });
const { application } = wpProduct;
const { type, config } = application;
assert(wpProduct.enabled && wpProduct.wpAccount?.enabled);
switch (type) {
case 'web': {
const { wechatPay } = config;
assert(wechatPay, 'web类型的application未配置wechatPay');
const appId = wechatPay.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, '暂时不支持');
}
}
}
},
};
export function getAccountEntity(entity) {
return PayClazzEntityDict[entity].accountEntity;
}
// 这里用一个flag来表达先后顺序如果有registerPayClazz框架应保证register在get之前
// 目前因为没有registerPayClazz所以没测可能不对。by Xc 20240608
let MODULE_USED = false;
export function registerPayClazz(entity, def, schema) {
assert(!MODULE_USED);
PayClazzEntityDict[entity] = {
accountEntity: def.accountEntity,
clazzConstructor: def.clazzConstructor,
};
// 检查此entity是否符合注册要求
// entity应该是AbstractPayProduct的子类accountEntity应该是AbstractPayAccount的子类
const { attributes: payAttrs } = schema.pay;
const { attributes: accountAttrs } = schema[def.accountEntity];
const { attributes: productAttrs } = schema[entity];
assert(payAttrs.entity.ref?.includes(entity));
assert(accountAttrs.price && (accountAttrs.price.type === 'decimal' || accountAttrs.price.type === 'money'));
assert(accountAttrs.systemId && accountAttrs.systemId.type === 'ref' && accountAttrs.systemId.ref === 'system');
assert(accountAttrs.allowWithdrawTransfer.type === 'boolean');
assert(accountAttrs.withdrawTransferLossRatio.type === 'decimal');
assert(productAttrs.applicationId.type === 'ref' && productAttrs.applicationId.ref === 'application');
assert(productAttrs.enabled.type === 'boolean');
const attrDict = {
taxLossRatio: 'decimal',
refundGapDays: 'int',
refundCompensateRatio: 'int',
needReceiving: 'boolean',
};
for (const attr in attrDict) {
assert(accountAttrs[attr].type === attrDict[attr]);
assert(productAttrs[attr].type === attrDict[attr]);
}
registerAccountEntity(def.accountEntity);
}
export async function getPayClazz(entity, entityId, context) {
if (!MODULE_USED) {
MODULE_USED = true;
}
const key = entity === 'account' ? entity : `${entity}.${entityId}`;
if (PayChannelDict.hasOwnProperty(key)) {
return PayChannelDict[key];
}
const PayClazz = await PayClazzEntityDict[entity].clazzConstructor(entityId, context);
PayChannelDict[key] = PayClazz;
return PayClazz;
}