JPOS Q2中ISORequestListener如何实现特定交易自定义响应
问题
我正尝试将原生JPOS项目迁移至Q2框架,目前遇到一个实现难题:需要在ISORequestListener中为用户指定的特定交易返回自定义响应,其余交易保持自动响应。
当前我的工具会接收JSON消息,其中指定了收单方请求消息的发送字段,以及发卡方需要返回的响应字段,示例如下:
{"messages": [ {"msgName": "Transaction - 01", "acquirer": { "delay": 5, "out": { //send out these fields in the outgoing request "0": "0100", "2": "9999999999999999", "3": "000000", "4": "000000045000", "6": "000000045000", ... }, "in": {} }, "issuer": { "in": {}, "out": { //Issuer responds with these custom fields for this specific txn, other txns auto-respond "0": "0110", "39": "05" } } } ]}
以下是我为发卡方配置的Q2相关内容:
<channel-adaptor name="iss-channel" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2"> <channel class="org.jpos.iso.channel.CSChannel" packager="org.jpos.iso.packager.GenericPackager" logger="Q2"> <property name="packager-config" value="src/main/resources/iso4.xml" /> <property name="host" value="10.xxx.xxx.xx" /> <property name="port" value="9999" /> <property name="timeout" value="300000" /> </channel> <in>iss-channel-send</in> <out>iss-channel-receive</out> <reconnect-delay>10000</reconnect-delay> </channel-adaptor> <mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="iss-mux" realm="acq-realm"> <in>iss-channel-receive</in> <out>iss-channel-send</out> <ready>iss-channel.ready</ready> <request-listener class="AutoResponder"></request-listener> </mux>
AutoResponder类代码如下:
import org.jpos.core.Configurable; import org.jpos.core.Configuration; import org.jpos.core.ConfigurationException; import org.jpos.iso.ISOMsg; import org.jpos.iso.ISORequestListener; import org.jpos.iso.ISOSource; public class AutoResponder implements ISORequestListener, Configurable { private Configuration cfg; @Override public void setConfiguration(Configuration cfg) throws ConfigurationException { this.cfg = cfg; } @Override public boolean process(ISOSource source, ISOMsg m) { try { ISOMsg r = (ISOMsg) m.clone(); r.setResponseMTI(); r.set(39, cfg.get("rc", "00")); source.send(r); } catch (Exception e) { throw new RuntimeException("Could not process message"); } return true; } }
当前配置可实现所有交易的自动响应,但我需要针对QA环境的负面测试,根据用户需求修改部分发卡方响应。请问如何基于Q2的ISORequestListener,为特定交易发送自定义字段,同时保持其余交易自动响应?
此前我的工具通过两个线程(收单方、发卡方各一个)构建请求/响应并调用BaseChannel.send()发送,但不确定如何在Q2的ISORequestListener中实现该逻辑。
解决方案
1. 新增自定义响应规则存储组件
实现一个单例类,用来加载、存储和查询用户指定的交易响应规则,支持从JSON配置中读取数据:
import java.util.HashMap; import java.util.Map; import com.fasterxml.jackson.databind.ObjectMapper; // 对应JSON结构的实体类 class TransactionRule { private String msgName; private AcquirerConfig acquirer; private IssuerConfig issuer; // 省略getter/setter static class AcquirerConfig { private int delay; private Map<String, String> out; private Map<String, String> in; // 省略getter/setter } static class IssuerConfig { private Map<String, String> in; private Map<String, String> out; // 省略getter/setter } } public class CustomResponseRepository { private static final CustomResponseRepository INSTANCE = new CustomResponseRepository(); // 用交易唯一标识(如PAN+交易码)作为key,存储对应发卡方响应规则 private final Map<String, TransactionRule.IssuerConfig> issuerResponseMap = new HashMap<>(); private CustomResponseRepository() {} public static CustomResponseRepository getInstance() { return INSTANCE; } // 加载JSON配置到内存 public void loadConfig(String jsonContent) throws Exception { ObjectMapper mapper = new ObjectMapper(); Map<String, Object> root = mapper.readValue(jsonContent, Map.class); for (Object msgObj : (Iterable<?>) root.get("messages")) { TransactionRule rule = mapper.convertValue(msgObj, TransactionRule.class); // 生成交易唯一标识,可根据业务调整规则 String key = rule.getAcquirer().getOut().get("2") + "_" + rule.getAcquirer().getOut().get("3"); issuerResponseMap.put(key, rule.getIssuer()); } } // 根据请求消息查询自定义响应规则 public TransactionRule.IssuerConfig findIssuerResponse(ISOMsg request) throws Exception { String pan = request.getString(2); String procCode = request.getString(3); String key = pan + "_" + procCode; return issuerResponseMap.get(key); } }
2. 修改AutoResponder类,加入规则匹配逻辑
在原有自动响应逻辑基础上,增加自定义规则判断:有匹配规则则应用自定义字段,无规则则保持默认自动响应:
import org.jpos.core.Configurable; import org.jpos.core.Configuration; import org.jpos.core.ConfigurationException; import org.jpos.iso.ISOMsg; import org.jpos.iso.ISORequestListener; import org.jpos.iso.ISOSource; import java.nio.file.Files; import java.nio.file.Paths; public class AutoResponder implements ISORequestListener, Configurable { private Configuration cfg; @Override public void setConfiguration(Configuration cfg) throws ConfigurationException { this.cfg = cfg; // 从配置指定路径加载自定义规则JSON try { String rulePath = cfg.get("rule-path"); String jsonContent = new String(Files.readAllBytes(Paths.get(rulePath))); CustomResponseRepository.getInstance().loadConfig(jsonContent); } catch (Exception e) { throw new ConfigurationException("Failed to load custom response rules", e); } } @Override public boolean process(ISOSource source, ISOMsg m) { try { ISOMsg r = (ISOMsg) m.clone(); r.setResponseMTI(); // 查询当前交易的自定义响应规则 TransactionRule.IssuerConfig customRule = CustomResponseRepository.getInstance().findIssuerResponse(m); if (customRule != null && customRule.getOut() != null) { // 应用所有自定义响应字段 for (Map.Entry<String, String> entry : customRule.getOut().entrySet()) { int fieldId = Integer.parseInt(entry.getKey()); r.set(fieldId, entry.getValue()); } } else { // 无自定义规则,使用默认自动响应 r.set(39, cfg.get("rc", "00")); } source.send(r); } catch (Exception e) { throw new RuntimeException("Could not process message", e); } return true; } }
3. 调整Q2配置,添加规则路径参数
在mux的请求监听器配置中,指定自定义规则的JSON文件路径:
<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="iss-mux" realm="acq-realm"> <in>iss-channel-receive</in> <out>iss-channel-send</out> <ready>iss-channel.ready</ready> <request-listener class="AutoResponder"> <property name="rc" value="00"/> <!-- 指定自定义规则JSON文件的路径 --> <property name="rule-path" value="src/main/resources/custom_response_rules.json"/> </request-listener> </mux>
4. 可选:动态更新规则
如果需要在Q2运行时动态更新规则,可以新增一个JMX接口或HTTP接口,调用CustomResponseRepository.getInstance().loadConfig()方法重新加载JSON配置,无需重启Q2。
内容的提问来源于stack exchange,提问作者tytyty
相关产品推荐
相关产品推荐

