You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ATM系统JavaScript开发:转出功能收款方账号验证问题咨询

解决ATM系统转出功能的收款方验证及转账逻辑问题

看起来你已经搭好了不错的基础框架,但转出功能的核心逻辑有几个需要调整的地方:一是收款方的验证逻辑不需要密码(现实中ATM转账只需要确认收款账号存在即可),二是当前的交易设计把转出单独拆成了transferReg,这不符合实际流程——转账应该由转出方发起,验证自身身份后再验证收款方账号,同时完成双方账户的金额变动。

下面是调整后的完整代码,我会标注关键修改点:

<!DOCTYPE html>
<html>
<head>
<title>Trial</title>
</head>
<body>
<h1>$ Trial $</h1>
<script type="text/javascript">
verify();
function Bank(bankName, bankCode){
 this.bankName = bankName;
 this.bankCode = bankCode;
 this.accounts = [];
 this.registerAccount = function(accountInfo){
 this.accounts.push({info: accountInfo, balance: 0});
 }
 // 新增:银行内通过账号查找账户(无需密码)
 this.findAccountByCode = function(accountCode){
   return this.accounts.reduce(function(acc, cur){
     return cur.info.code === accountCode ? cur : acc;
   }, null);
 }
}
function ATM(initCurrency){
 this.currency = initCurrency;
 this.banks = [];
 this.registerBank = function(bank){
 this.banks.push(bank);
 }
 this.auth = function(authinfo){
 return {
 authinfo: authinfo,
 operations:[],
 deposit: function(amount){
 this.operations.push({type: 'deposit', amount: amount});
 },
 withdraw: function(amount){
 this.operations.push({type: 'withdraw', amount: amount});
 },
 transferIn: function(amount){
 this.operations.push({type: 'transfer-in', amount: amount});
 },
 // 关键修改:把转出功能整合到已授权的交易中,接收收款方信息
 transferOut: function(receiverInfo, amount){
 this.operations.push({
   type: 'transfer-out', 
   amount: amount,
   receiver: receiverInfo // 存储收款方信息用于后续验证
 });
 },
 getBalance: function(){
 this.operations.push({type: 'balance-view'});
 },
 }
 }
 // 新增:验证收款方账号(仅需银行代码和账号存在)
 this.findReceiverAccount = function(receiverInfo){
   const bank = this.banks.reduce(function(acc, cur){
     return cur.bankCode === receiverInfo.bankCode ? cur : acc;
   }, null);
   return bank ? bank.findAccountByCode(receiverInfo.code) : null;
 }
 this.currencyLeft = function() {
 return (this.currency);
 }
 this.commit = function(transaction){
 // 先验证转出方身份
 const senderAccount = this.findAccount(transaction.authinfo);
 if(!senderAccount){
 return {status: 'FAILURE', reason: '转出方身份验证失败'}
 }
 let result = {status: 'SUCCESS'}
 const commitedOperations = []
 for (let operation of transaction.operations){
 commitedOperations.push(operation);
 switch (operation.type){
 case 'deposit':
 senderAccount.balance += operation.amount;
 this.currency += operation.amount;
 break;
 case 'withdraw':
 senderAccount.balance -= operation.amount;
 this.currency -= operation.amount;
 break;
 case 'transfer-in':
 // 转入功能按原有逻辑:外部转入增加ATM现金
 senderAccount.balance += operation.amount;
 this.currency += operation.amount;
 break;
 case 'transfer-out':
 // 关键修改:验证收款方账号是否存在
 const receiverAccount = this.findReceiverAccount(operation.receiver);
 if(!receiverAccount){
   result.status = 'FAILURE';
   result.reason = '收款方账号不存在';
   break;
 }
 // 检查转出方余额是否足够
 if(senderAccount.balance < operation.amount){
   result.status = 'FAILURE';
   result.reason = '余额不足';
   break;
 }
 // 完成转账:转出方减额,转入方加额,ATM现金不变(账户间转账不涉及现金)
 senderAccount.balance -= operation.amount;
 receiverAccount.balance += operation.amount;
 break;
 case 'balance-view':
 result.data = senderAccount.balance;
 break;
 }
 if(result.status === 'FAILURE'){
 break;
 }
 }
 // 交易失败时的回滚逻辑
 if(result.status === 'FAILURE'){
 while(commitedOperations.length){
 let undoOperation = commitedOperations.pop();
 switch(undoOperation.type){
 case 'deposit':
 senderAccount.balance -= undoOperation.amount;
 this.currency -= undoOperation.amount;
 break;
 case 'withdraw':
 senderAccount.balance += undoOperation.amount;
 this.currency += undoOperation.amount;
 break;
 case 'transfer-in':
 // 修复原有bug:把错误的amount.balance改为senderAccount.balance
 senderAccount.balance -= undoOperation.amount;
 this.currency -= undoOperation.amount;
 break;
 case 'transfer-out':
 const receiverAccount = this.findReceiverAccount(undoOperation.receiver);
 if(receiverAccount){
   senderAccount.balance += undoOperation.amount;
   receiverAccount.balance -= undoOperation.amount;
 }
 break;
 case 'balance-view':
 delete result.data;
 break;
 }
 }
 }
 return result;
 }
 this.findAccount = function(authinfo){
 var bank = this.banks.reduce(function(acc, cur){
 return (cur.bankCode === authinfo.bankCode) ? cur : acc
 }, null);
 return bank ? bank.accounts.reduce(function(acc, cur){
 return(cur.info.code === authinfo.code && cur.info.password === authinfo.password) ? cur : acc
 }, null) : null
 }
}
function verify(){
 var bankName = 'Standard Chartered';
 var bankCode = 52;
 var bank = new Bank(bankName, bankCode);
 // 注册转出方账号
 const senderInfo = {
 name: 'John',
 code: 113322,
 password: 223333,
 }
 bank.registerAccount(senderInfo);
 // 新增:注册收款方测试账号
 const receiverInfo = {
 name: 'Thomas',
 code: 1234567,
 password: '123456',
 }
 bank.registerAccount(receiverInfo);
 var initCurrency = 1000
 var atm = new ATM(initCurrency);
 atm.registerBank(bank);
 // 原有基础功能测试用例
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'SUCCESS');
 console.log(result.data === 0);
 }
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.deposit(5600);
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'SUCCESS');
 console.log(result.data === 5600);
 }
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.withdraw(3000);
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'SUCCESS');
 console.log(result.data === 2600);
 }
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.transferIn(2000);
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'SUCCESS');
 console.log(result.data === 4600);
 }
 // 修改转账测试用例:使用正确的收款账号
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.transferOut({bankCode: 52, code: 1234567}, 2000);
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'SUCCESS');
 console.log(result.data === 2600);
 // 额外验证收款方余额是否正确增加
 const receiverAccount = atm.findReceiverAccount({bankCode:52, code:1234567});
 console.log(receiverAccount.balance === 2000);
 }
 console.log(atm.currencyLeft() === 3600); // 转账不影响ATM现金,数值保持不变
 // 测试收款方账号不存在的失败场景
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.transferOut({bankCode: 52, code: 987654}, 1000);
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'FAILURE');
 console.log(result.reason === '收款方账号不存在');
 }
 // 原有其他失败测试用例
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 2233});
 transaction.withdraw(3000);
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'FAILURE');
 }
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.withdraw(1000);
 transaction.withdraw(1000);
 transaction.withdraw(1000);
 transaction.withdraw(1000);
 transaction.withdraw(1000);
 transaction.withdraw(1000);
 transaction.withdraw(1000);
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'FAILURE');
 }
 {
 let transaction = atm.auth({bankCode: 52, code: 113322, password: 223333});
 transaction.getBalance();
 let result = atm.commit(transaction);
 console.log(result.status === 'SUCCESS');
 console.log(result.data === 2600);
 }
}
</script>
</body>
</html>

关键修改说明:

  1. 收款方验证逻辑优化:

    • 在Bank类中新增findAccountByCode方法,仅通过账号查找账户,不需要验证密码(符合现实ATM转账的逻辑)。
    • ATM类新增findReceiverAccount方法,专门负责验证收款方的银行代码和账号是否真实存在。
  2. 转账功能流程重构:

    • 移除了单独的transferReg方法,将transferOut整合到已授权的交易对象中——转账必须由已验证身份的转出方发起,更贴近实际操作流程。
    • transferOut方法接收收款方的银行代码和账号信息,将这些信息存入操作记录,方便后续commit时进行验证和处理。
  3. 转账交易核心处理:

    • 在commit处理transfer-out操作时,先验证收款账户是否存在,再检查转出方余额是否足够,最后同时修改转出方和转入方的余额(ATM现金不变,因为账户间转账不涉及现金存取)。
  4. 修复原有代码bug:

    • 修正了回滚逻辑中transfer-in操作的错误(原代码错误使用amount.balance,改为正确的senderAccount.balance)。
    • 补充了收款账户的注册代码,确保转账测试用例可以正常运行。

这样调整后,转出功能的收款方验证逻辑就符合要求了,整个转账流程也更贴近实际的ATM操作逻辑。

内容的提问来源于stack exchange,提问作者Melody Mak

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.01 02:18:11