commit
bbcd47f6f8
44 changed files with 5121 additions and 0 deletions
@ -0,0 +1,11 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<classpath> |
||||
<classpathentry kind="src" path="src"/> |
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/CDC-1.0%Foundation-1.0"/> |
||||
<classpathentry exported="true" kind="con" path="org.eclipse.jdt.USER_LIBRARY/CORE_LIBS"/> |
||||
<classpathentry kind="lib" path="lib/eftlink.jar"/> |
||||
<classpathentry kind="lib" path="lib/log4j-1.2-api-2.16.0.jar"/> |
||||
<classpathentry kind="lib" path="lib/log4j-api-2.16.0.jar"/> |
||||
<classpathentry kind="lib" path="lib/log4j-core-2.16.0.jar"/> |
||||
<classpathentry kind="output" path="bin"/> |
||||
</classpath> |
||||
@ -0,0 +1,17 @@ |
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<projectDescription> |
||||
<name>HYWEB-N5Core</name> |
||||
<comment></comment> |
||||
<projects> |
||||
</projects> |
||||
<buildSpec> |
||||
<buildCommand> |
||||
<name>org.eclipse.jdt.core.javabuilder</name> |
||||
<arguments> |
||||
</arguments> |
||||
</buildCommand> |
||||
</buildSpec> |
||||
<natures> |
||||
<nature>org.eclipse.jdt.core.javanature</nature> |
||||
</natures> |
||||
</projectDescription> |
||||
@ -0,0 +1,2 @@ |
||||
eclipse.preferences.version=1 |
||||
encoding/<project>=UTF-8 |
||||
@ -0,0 +1,12 @@ |
||||
eclipse.preferences.version=1 |
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled |
||||
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate |
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 |
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve |
||||
org.eclipse.jdt.core.compiler.compliance=1.8 |
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate |
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate |
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate |
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error |
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error |
||||
org.eclipse.jdt.core.compiler.source=1.8 |
||||
@ -0,0 +1,282 @@ |
||||
# Eftlink Configuration Properties |
||||
################################## |
||||
|
||||
# Basic Settings |
||||
################ |
||||
|
||||
# Socket config for OPI Server |
||||
ServerChannel0 = 10100 |
||||
ServerChannel1 = 10101 |
||||
#Channel1IP = 1.2.3.4 |
||||
|
||||
# Whether to use secure TLS socket communication. Default true. This feature should not be disabled |
||||
# without express authorisation from Oracle. |
||||
TLSEnabled = true |
||||
|
||||
# OPIServerDelegate - allows OPIServer operation to be delegated to an alternate class |
||||
# e.g. an extended class to include tracking/logging |
||||
#OPIServerDelegate = manito.eft.tlog.TLogOPIServer |
||||
|
||||
|
||||
# EFTLink Server (single multi-client host) setup |
||||
################################################# |
||||
|
||||
# Number of eftlink instances to be hosted. Set to zero to run standard EFTLink application. |
||||
NumServers = 0 |
||||
|
||||
# Whether EFTLink is to be accessed via a single common server socket, with messages routed by POS ID |
||||
# Note - in this mode, channel 1 will run on the same client socket as channel 0. |
||||
SingleSocket = false |
||||
|
||||
# server/ped identifier list - mandatory when using ped pool. 1-based. |
||||
server1.description = EFT 1 |
||||
server2.description = EFT 2 |
||||
|
||||
# Whether to run a pool of PED shared between POSs. (many-many link) |
||||
# Note - this option not available in SingleSocket mode. |
||||
PEDPoolEnabled = false |
||||
|
||||
# Number of potential POS clients when using PED pool. |
||||
#NumClients = 2 |
||||
|
||||
# pos identifier list - mandatory when using ped pool. 1-based. |
||||
pos1.description = POS 1 |
||||
pos2.description = POS 2 |
||||
|
||||
# sub-pool restrictions/pre-selections. prefix the server id with '*' to specify a default association. |
||||
pos1.subpool = *EFT 1, EFT 2 |
||||
pos2.subpool = EFT 1, EFT 2 |
||||
|
||||
# Whether to run a pool of printers shared between POSs. (many-many link) |
||||
# Printer pool is accessed via the "master" channel 0. Channel 1 will run on the same client socket as channel 0. |
||||
PrinterPoolEnabled = false |
||||
|
||||
|
||||
# Environment Settings |
||||
###################### |
||||
|
||||
# POS type that EftLink is connected to. This can be set explicitly (e.g. Lucas, |
||||
# Retail-J, Oscar) or set to "Auto" for the POS type to be deduced from the OPI |
||||
# message header |
||||
PosType = auto |
||||
|
||||
|
||||
################################################################################### |
||||
# |
||||
# Configuration Hierarchy |
||||
# ----------------------- |
||||
# |
||||
# The settings immediately below may be set in two different ways. |
||||
# 1. as a default value determined by the PosType. |
||||
# 2. as a setting in this file, overriding any value set in 1 above. To avoid |
||||
# overriding the pos-dependent defaults, settings have to be commented-out |
||||
# in this file. |
||||
# |
||||
#################################################################################### |
||||
|
||||
|
||||
# Static/Dynamic Configuration |
||||
############################## |
||||
|
||||
# Eftlink can be configured to pick up its configuration dynamically from POS |
||||
# messages. A default setting is implied by the POS type setting above, but this |
||||
# can be overridden. |
||||
|
||||
#DynamicConfiguration = false |
||||
|
||||
# The level of IFSF compliance for the POS interface - IFSF or LUCAS |
||||
#PosIfsfCompliance = LUCAS |
||||
|
||||
|
||||
|
||||
################################################################################### |
||||
# |
||||
# Configuration Hierarchy |
||||
# ----------------------- |
||||
# |
||||
# All the remaining settings may be set in three different ways. |
||||
# 1. as a default value determined by the PosType. |
||||
# 2. as a setting in this file, overriding any value set in 1 above. To avoid |
||||
# overriding the pos-dependent defaults, settings have to be commented-out |
||||
# in this file. |
||||
# 3. as a dynamic setting in a message from the POS (if this feature |
||||
# is enabled), overriding any value set in 1 or 2 above. |
||||
# |
||||
#################################################################################### |
||||
|
||||
|
||||
# Language / Internationalisation |
||||
################################# |
||||
|
||||
# Language for display texts. For whatever country code is set, there must be a |
||||
# matching LangXX.properties file. A hierarchy is implied e.g. EN_US is taken as |
||||
# an extension of EN |
||||
DisplayLanguage = EN |
||||
|
||||
# Number of decimal places to show |
||||
DecimalPlaces = 2 |
||||
|
||||
|
||||
# number and type of EPS sub-systems |
||||
#################################### |
||||
|
||||
# built-in cores can be specified by short name e.g Simulated, OPIClient. |
||||
# plugin cores must be specified by their full package name, and the package |
||||
# must be added to the execution classpath |
||||
NumEPSCores = 1 |
||||
EPSCore0 = Simulated |
||||
#EPSCore0 = OPIClient ATS |
||||
#EPSCore1 = OPIClient Loyalty |
||||
#EPSCore2 = CardReader |
||||
|
||||
# Secondary server socket for reentrant calling into Eftlink from core 0. |
||||
# All such messages received on this socket must go to a single designated core, other than core 0. |
||||
# SecondaryServer: ServerSocket port number |
||||
#SecondaryServerPort = 10200 |
||||
# SecondaryServerCore: core to which secondary messages will be passed |
||||
#SecondaryServerCore = 1 |
||||
|
||||
# A particular core can be designated to handle loyalty operations. If not set, they go to core 0. |
||||
# LoyaltyCore: core designated for Loyalty requests. |
||||
#LoyaltyCore = 1 |
||||
|
||||
# A particular core can be designated for handling card swipe/read requests. If not set, they go to core 0. |
||||
# CardReaderCore: core designated for CardSwipe/CardRead requests. |
||||
#CardReaderCore = 2 |
||||
# Cores can also delegate card reading to the card reader e.g to read the card as part of a LoyaltyAward. |
||||
# CardReaderCoreDelegateList: CSV list of cores delegating their card reading. |
||||
#CardReaderCoreDelegateList = 0,1 |
||||
|
||||
# The POS can be designated for handling card swipe/read requests. If not set, they go to core 0. |
||||
# POSCardReader - boolean, default false. Sets whether the POS is to be used for CardSwipe/CardRead requests. |
||||
POSCardReader = false |
||||
# Cores can also delegate card reading to the POS card reader e.g to read the card as part of a LoyaltyAward. |
||||
# POSCardReaderDelegateList: CSV list of cores delegating their card reading. |
||||
#POSCardReaderDelegateList = 0,1 |
||||
|
||||
# A particular core can be designated to handle Agent operations (e.g.bill payment, telephone top-up). If not set, they |
||||
# go to core 0. |
||||
# AgentCore: core designated for agent requests. |
||||
#AgentCore = 1 |
||||
|
||||
|
||||
# Channel 1 device proxy settings |
||||
################################# |
||||
|
||||
# Whether to use a display server delegate class to control pop-up dialogs directly from EftLink instead of via Channel1 |
||||
DelegatedDisplay = false |
||||
|
||||
# DelegatedDisplay parameters |
||||
# DelegatedDisplayHandler - class implementing pop-up dialogs. default - manito.deviceproxy.DeviceProxy |
||||
# DisplayScheme - scheme name defining screen layout and colours. default - xxx |
||||
# DisplayLayout - optional secondary scheme name defining different layouts based on the same colour scheme |
||||
# DelegatedDisplayOverride - optional override to revert some display operations back to the POS e.g. to support |
||||
# alternate input sources. |
||||
# None (default) - no overrides, all input/output request handled by delegated display |
||||
# KeyedInput - keypad/keyboard reverted to POS |
||||
# AllInput - all input request reverted to POS |
||||
#DisplayScheme = iridium |
||||
#DisplayLayout = default |
||||
#DelegatedDisplayOverride = KeyedInput |
||||
# Other settings are available in the scheme definition file. |
||||
|
||||
# whether to precede each print request with a TXT_PRINTING (e.g. "Printing. Please Wait") dialog. |
||||
ShowPrintingDialog = false |
||||
|
||||
# Whether to request forced input (no cancellation) on input requests to the POS, if not explicitly set by the core. |
||||
ForcedInput = false |
||||
|
||||
# whether device events e.g. CardInserted are supported by the POS. Boolean, default false. This is normally set |
||||
# automatically based on the POS type, but can be explicitly set here. |
||||
#DeviceEvents = |
||||
|
||||
|
||||
# POS settings |
||||
############## |
||||
|
||||
# Whether combined payment with loyalty is supported - default true |
||||
# N.B. combined payment with loyalty is automatically disabled if a part payment |
||||
# is detected. |
||||
PaymentWithLoyalty = true |
||||
|
||||
# Whether SaleItem values should be validated to ensure that the sum of the items matches the overall value |
||||
# defaults to true |
||||
ValidateItemValues=true |
||||
|
||||
# whether the printer status is implied online |
||||
# i.e. if the POS can only send requests when the printer is online and with paper, |
||||
# we do not need an explicit check |
||||
#PrinterImpliedOnline = true |
||||
|
||||
|
||||
# currency symbol conversion |
||||
CURRENCY_156 = GBP |
||||
CURRENCY_163 = GBP |
||||
CURRENCY_164 = EUR |
||||
CURRENCY_213 = EUR |
||||
|
||||
|
||||
# Spooled print options |
||||
####################### |
||||
# DespoolOnLogon - spooled reports are automatically printed on next logon. default false |
||||
# DespoolOnMaintenance - spooled reports are automatically printed on next maintenance/administration use. default true |
||||
# DespoolOnReconciliation - spooled reports are automatically printed at next shift close. default true |
||||
|
||||
|
||||
# Dayend settings |
||||
################# |
||||
|
||||
# Whether Eftlink is to relay POS reconciliation message on to other instances of EftLink |
||||
# If set true, EftLink uses the same dayend client list as for manito.eft.opi.server.Dayend below |
||||
DistributedDayend = false |
||||
|
||||
# List of client systems to which a reconciliation message should be sent by the manito.eft.opi.server.Dayend operation. |
||||
# NumDayendClients - number of clients to be processed |
||||
# DayendClientxIP - IP of remote system where EftLink is running |
||||
# DayendClientxChannel0 - Port which EftLink is running on, usually 10100 |
||||
# DayendClientxBatch - batch file to be run locally instead of sending message |
||||
# DayendClientxCore - specific individual core to send the request to |
||||
NumDayendClients = 1 |
||||
DayendClient0IP=127.0.0.1 |
||||
DayendClient0Channel0=10100 |
||||
#DayendClient0Core = EftDevice |
||||
#DayendClient0Batch = dayend.bat |
||||
#DayendClient1IP=127.0.0.1 |
||||
DayendClient1Channel0=10100 |
||||
#DayendClient2IP=127.0.0.1 |
||||
DayendClient2Channel0=10100 |
||||
#DayendClient3IP=127.0.0.1 |
||||
DayendClient3Channel0=10100 |
||||
#DayendClient4IP=127.0.0.1 |
||||
DayendClient4Channel0=10100 |
||||
|
||||
#Crypto-Agility - Communications |
||||
#Protocols Secure setting |
||||
ProtocolsWhiteList=SSLv2Hello,TLSv1.2 |
||||
#Protocols Default |
||||
#ProtocolsWhiteList=SSLv2Hello,TLSv1.2 |
||||
#Protocols Java 1.6 setting for backwards compatibility |
||||
#ProtocolsWhiteList=SSLv2Hello,TLSv1.2,TLSv1,TLSv1.1 |
||||
#Cipher Secure setting |
||||
CipherWhiteList=TLS_DHE_.*_WITH_AES_128_.*,TLS_ECDHE_.*_WITH_AES_128_.*,TLS_ECDH_.*_WITH_AES_128_.* |
||||
CipherBlackList=SSL_.*,TLS_EMPTY_.*,.*_SHA,.*_3DES_.*,.*_DES_.*,.*_WITH_NULL_.*,.*_anon_.* |
||||
#Cipher Default |
||||
#CipherWhiteList=TLS_DHE_.*_WITH_AES_128_.*,TLS_ECDHE_.*_WITH_AES_128_.*,TLS_ECDH_.*_WITH_AES_128_.* |
||||
#CipherBlackList=SSL_.*,TLS_EMPTY_.*,.*_SHA,.*_3DES_.*,.*_DES_.*,.*_WITH_NULL_.*,.*_anon_.* |
||||
#Cipher Java 1.6 setting for backwards compatibility |
||||
#CipherWhiteList= |
||||
#CipherBlackList=SSL_.* |
||||
|
||||
|
||||
# Allow the application to correctly secure access to data folders when running under the Windows Local System |
||||
# account. It is strongly recommended that the application is not configured to run using the Windows Local |
||||
# System account, instead use the Windows Local Service account when use of a local Windows machine account is |
||||
# desired. Note that the Windows Network Service account should not be used. |
||||
# Default value for this setting is false. |
||||
AllowMapMachineNameToSystemAccount= |
||||
|
||||
#Proxy settings - Set the proxy server details when EFTLink runs in an environment where all http outbound calls are routed to a proxy. |
||||
#https.proxyHost=adc-proxy.oracle.com |
||||
#https.proxyPort=80 |
||||
#http.proxyHost=adc-proxy.oracle.com |
||||
#http.proxyPort=80 |
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,9 @@ |
||||
package com.hyweb.n5.eftcore; |
||||
|
||||
public class Constants { |
||||
public static final String Entry_Swipe = "Magstripe"; |
||||
public static final String Entry_Manual = "Manual"; |
||||
public static final String Entry_Chip = "Chip"; |
||||
public static final String Entry_Contactless = "Contactless"; |
||||
public static final String Entry_Unknown = "Unknown"; |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,5 @@ |
||||
package com.hyweb.n5.eftcore; |
||||
|
||||
public class Version { |
||||
public static final String VERSION = "HYWEB_N5 Core v3.09"; |
||||
} |
||||
@ -0,0 +1,266 @@ |
||||
package com.hyweb.n5.eftcore.message; |
||||
|
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.concurrent.atomic.AtomicInteger; |
||||
|
||||
public class JsonParser { |
||||
|
||||
private final String json; |
||||
|
||||
public JsonParser(String json) { |
||||
this.json = json; |
||||
} |
||||
|
||||
|
||||
|
||||
public Object parse() { |
||||
CharsRange trimmedJson = newRange(0, json.length()).trim(); |
||||
return processValue(trimmedJson); |
||||
} |
||||
|
||||
private Object processPlainObject(CharsRange range) { |
||||
List<Property> properties = processProperties(newRange(range.start + 1, range.end - 1)); |
||||
Map<String, Object> object = new HashMap<>(); |
||||
//properties.forEach(prop -> object.put(prop.name, prop.value));
|
||||
|
||||
for (Property prop: properties) |
||||
{ |
||||
object.put(prop.name, prop.value); |
||||
} |
||||
return object; |
||||
} |
||||
|
||||
private List<Property> processProperties(CharsRange range) |
||||
{ |
||||
List<Property> properties = new ArrayList<>(); |
||||
int nameStartMark = range.start; |
||||
for (int i = range.start; i < range.end; i++) |
||||
{ |
||||
char ch = json.charAt(i); |
||||
if (ch == ':') |
||||
{ |
||||
CharsRange nameToken = newRange(nameStartMark, i).trim(); |
||||
AtomicInteger readCursor = new AtomicInteger(); |
||||
CharsRange valueSegment = findNextValue(newRange(++i, range.end), readCursor); |
||||
i = readCursor.intValue() + 1; |
||||
nameStartMark = i; |
||||
//Logger.info("nameToken:{},\nvalueSegment:{}", nameToken, valueSegment);
|
||||
//TODO::valid nameToken is start and end with '"'
|
||||
final String name = newRange(nameToken.start + 1, nameToken.end - 1).toString(); |
||||
final Object value = processValue(valueSegment); |
||||
properties.add(Property.of(name, value)); |
||||
} |
||||
} |
||||
return properties; |
||||
} |
||||
|
||||
private List<?> processArray(CharsRange range) |
||||
{ |
||||
return processElements(newRange(range.start + 1, range.end - 1)); |
||||
} |
||||
|
||||
private List<?> processElements(CharsRange range) |
||||
{ |
||||
List<Object> array = new ArrayList<>(); |
||||
int elementStartMark = range.start; |
||||
for (int i = range.start; i < range.end; i++) |
||||
{ |
||||
AtomicInteger readCursor = new AtomicInteger(); |
||||
CharsRange elementSegment = findNextValue(newRange(elementStartMark, range.end), readCursor); Object elementValue = processValue(elementSegment); |
||||
array.add(elementValue); |
||||
i = readCursor.intValue(); elementStartMark = i + 1; |
||||
} |
||||
return array; |
||||
} |
||||
|
||||
|
||||
private CharsRange findNextValue(CharsRange chars, AtomicInteger readCursor) |
||||
{ |
||||
CharsRange trimChars = chars.trimLeft(); |
||||
if (trimChars.relativeChar(0) == '{') |
||||
{ |
||||
return completeSymbolPair(trimChars, readCursor, "{}"); |
||||
} |
||||
else if (trimChars.relativeChar(0) == '[') |
||||
{ |
||||
return completeSymbolPair(trimChars, readCursor, "[]"); |
||||
} |
||||
else |
||||
{ |
||||
int i; |
||||
for (i = trimChars.start + 1; i < trimChars.end; i++) |
||||
{ |
||||
char ch = json.charAt(i); |
||||
if (ch == ',') |
||||
{ |
||||
break; |
||||
} |
||||
} |
||||
readCursor.set(i); |
||||
return newRange(trimChars.start, i).trim(); |
||||
} |
||||
} |
||||
|
||||
private CharsRange completeSymbolPair(CharsRange trimChars, AtomicInteger readCursor, String symbolPair) |
||||
{ |
||||
int leftSymbol = symbolPair.charAt(0); |
||||
int rightSymbol = symbolPair.charAt(1); |
||||
int symbolsScore = 1; //nested object
|
||||
int i; |
||||
CharsRange valueSegment = null; |
||||
for (i = trimChars.start + 1; i < trimChars.end; i++) |
||||
{ |
||||
char ch = json.charAt(i); |
||||
if (ch == leftSymbol) |
||||
{ |
||||
symbolsScore++; |
||||
} |
||||
else if (ch == rightSymbol) |
||||
{ |
||||
symbolsScore--; |
||||
} |
||||
if (symbolsScore == 0) { |
||||
valueSegment = newRange(trimChars.start, i + 1); |
||||
break; |
||||
} |
||||
} |
||||
|
||||
for (; i < trimChars.end; i++) |
||||
{ |
||||
char chx = json.charAt(i); |
||||
if (chx == ',') |
||||
{ |
||||
break; |
||||
} |
||||
} |
||||
readCursor.set(i); |
||||
return valueSegment; |
||||
} |
||||
|
||||
private Object processValue(CharsRange valueSegment) |
||||
{ |
||||
final Object value; |
||||
if (valueSegment.relativeChar(0) == '"') |
||||
{ |
||||
value = newRange(valueSegment.start + 1, valueSegment.end - 1).toString(); |
||||
} |
||||
else if (valueSegment.relativeChar(0) == '{') |
||||
{ |
||||
value = processPlainObject(valueSegment); |
||||
} |
||||
else if (valueSegment.relativeChar(0) == '[') |
||||
{ |
||||
value = processArray(valueSegment); |
||||
} |
||||
else if (valueSegment.equalsString("true")) |
||||
{ |
||||
value = true; |
||||
} |
||||
else if (valueSegment.equalsString("false")) |
||||
{ |
||||
value = false; |
||||
} |
||||
else if (valueSegment.equalsString("null")) |
||||
{ |
||||
value = null; |
||||
} |
||||
else |
||||
{ |
||||
value = Double.parseDouble(valueSegment.toString()); |
||||
} |
||||
return value; |
||||
} |
||||
|
||||
static class Property |
||||
{ |
||||
final String name; |
||||
final Object value; |
||||
Property(String name, Object value) |
||||
{ |
||||
this.name = name; this.value = value; |
||||
} |
||||
|
||||
static Property of(String name, Object value) |
||||
{ |
||||
return new Property(name, value); |
||||
} |
||||
} |
||||
|
||||
CharsRange newRange(int start, int end) { |
||||
return new CharsRange(start, end); |
||||
} |
||||
|
||||
|
||||
class CharsRange |
||||
{ |
||||
final int start; |
||||
final int end; |
||||
|
||||
CharsRange(int start, int end) |
||||
{ |
||||
this.start = start; |
||||
this.end = end; |
||||
} |
||||
|
||||
CharsRange trimLeft() |
||||
{ |
||||
int newStart = -1; |
||||
for (int i = start; i < end; i++) |
||||
{ |
||||
if (!Character.isWhitespace(json.charAt(i))) |
||||
{ |
||||
newStart = i; |
||||
break; |
||||
} |
||||
} |
||||
if (newStart == -1) |
||||
{ |
||||
throw new IllegalArgumentException("illegal blank string!"); |
||||
} |
||||
return newRange(newStart, end); |
||||
} |
||||
|
||||
CharsRange trimRight() |
||||
{ |
||||
int newEnd = -1; |
||||
for (int i = end - 1; i >= start; i--) |
||||
{ |
||||
if (!Character.isWhitespace(json.charAt(i))) |
||||
{ |
||||
newEnd = i + 1; |
||||
break; |
||||
} |
||||
} |
||||
if (newEnd == -1) |
||||
{ |
||||
throw new IllegalArgumentException("illegal blank string!"); |
||||
} |
||||
return newRange(start, newEnd); |
||||
} |
||||
|
||||
CharsRange trim() |
||||
{ |
||||
return this.trimLeft().trimRight(); |
||||
} |
||||
|
||||
char relativeChar(int index) |
||||
{ |
||||
return json.charAt(start + index); |
||||
} |
||||
|
||||
public boolean equalsString(String str) |
||||
{ |
||||
return json.regionMatches(true, start, str, 0, str.length()); |
||||
} |
||||
|
||||
@Override public String toString() |
||||
{ |
||||
return json.subSequence(start, end).toString(); |
||||
} |
||||
} |
||||
|
||||
|
||||
} |
||||
@ -0,0 +1,161 @@ |
||||
package com.hyweb.n5.eftcore.message; |
||||
|
||||
import java.math.BigDecimal; |
||||
import com.hyweb.n5.eftcore.message.utils.Utils; |
||||
|
||||
public class N5Message { |
||||
public final static byte STX = 0x02; |
||||
public final static byte ETX = 0x03; |
||||
|
||||
private final static int BytesOfLengthIndicator = 2; |
||||
//private final static int BytesOfMAC = 32;
|
||||
|
||||
private byte[] body; |
||||
private byte[] mac; |
||||
private boolean isDeviceDisplay; |
||||
private final static String DEVICE_DISPLAY_ALIAS = "devicedisplay:"; |
||||
public N5Message() |
||||
{} |
||||
|
||||
public byte[] getBody() { |
||||
return body; |
||||
} |
||||
|
||||
public void setBody(byte[] body) { |
||||
this.body = body; |
||||
|
||||
String tmpStr = new String(body); |
||||
if (tmpStr.startsWith(DEVICE_DISPLAY_ALIAS)) |
||||
isDeviceDisplay = true; |
||||
else |
||||
isDeviceDisplay = false; |
||||
} |
||||
|
||||
public byte[] getMac() { |
||||
return mac; |
||||
} |
||||
|
||||
public void setMac(byte[] mac) { |
||||
this.mac = mac; |
||||
} |
||||
|
||||
// private boolean parse(byte[] src)
|
||||
// {
|
||||
// int msglength = 0;
|
||||
//
|
||||
// if (src.length < (1 + 1 + BytesOfLengthIndicator + BytesOfMAC))
|
||||
// return false;
|
||||
// if (src[0] != STX)
|
||||
// return false;
|
||||
// if (src[src.length - 1] != ETX)
|
||||
// return false;
|
||||
//
|
||||
// byte[] len = new byte[] { src[1], src[2] };
|
||||
// String lenStr = Utils.bcd2Str(len);
|
||||
// msglength = Integer.parseInt(lenStr);
|
||||
//
|
||||
// if (src.length != (1 + 1 + msglength + BytesOfLengthIndicator + BytesOfMAC))
|
||||
// return false;
|
||||
//
|
||||
// System.arraycopy(src, 3, body, 0, msglength);
|
||||
// System.arraycopy(src, src.length - 2 - BytesOfMAC, mac, 0, BytesOfMAC);
|
||||
// return true;
|
||||
// }
|
||||
|
||||
public boolean isDeviceDisplay() { |
||||
return isDeviceDisplay; |
||||
} |
||||
|
||||
public byte[] toBytes(){ |
||||
if (null == body || null == mac) |
||||
return null; |
||||
byte[] result = new byte[2 + BytesOfLengthIndicator + body.length + mac.length]; |
||||
byte[] len = Utils.str2Bcd(Utils.addZeroForNum(Integer.toString(body.length), 4)); |
||||
result[0] = STX; |
||||
result[1] = len[0]; |
||||
result[2] = len[1]; |
||||
|
||||
System.arraycopy(body, 0, result, 3, body.length); |
||||
System.arraycopy(mac, 0, result, body.length + 3, mac.length); |
||||
result[result.length-1] = ETX; |
||||
return result; |
||||
} |
||||
|
||||
public static String createParamRequestJsonMsg() |
||||
{ |
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"PARAM\","); |
||||
respMsg.append("\"PAYMENT_APP_ID\":\"CC\"}"); |
||||
return respMsg.toString(); |
||||
} |
||||
|
||||
public static String createTxnInquiryRequestJsonMsg(String txnId) |
||||
{ |
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"RETRIEVAL\","); |
||||
respMsg.append("\"TXN_ID\":\"" + txnId + "\"}"); |
||||
return respMsg.toString(); |
||||
} |
||||
|
||||
public static String createCardPurchaseRequestJsonMsg(String txnId, BigDecimal txnAmt, BigDecimal tipAmt, String paymentAppId, String qrcValue, boolean ifPrintSS) |
||||
{ |
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"SALE\","); |
||||
respMsg.append("\"TXN_ID\":\"" + txnId + "\","); |
||||
respMsg.append("\"TXN_AMT\":" + txnAmt + ","); |
||||
if (null != tipAmt) |
||||
respMsg.append("\"TIPS\":" + tipAmt + ","); |
||||
respMsg.append("\"PAYMENT_APP_ID\":\"" + paymentAppId + "\","); |
||||
if (null != qrcValue) |
||||
respMsg.append("\"QRC_VALUE\":\"" + qrcValue + "\","); |
||||
respMsg.append("\"PRINT_SS\":" + ifPrintSS + "}"); |
||||
|
||||
return respMsg.toString(); |
||||
} |
||||
|
||||
public static String createCardRefundRequestJsonMsg(String txnId, BigDecimal txnAmt, String paymentAppId, String qrcValue, boolean ifPrintSS) |
||||
{ |
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"REFUND\","); |
||||
respMsg.append("\"TXN_ID\":\"" + txnId + "\","); |
||||
respMsg.append("\"TXN_AMT\":" + txnAmt + ","); |
||||
respMsg.append("\"PAYMENT_APP_ID\":\"" + paymentAppId + "\","); |
||||
if (null != qrcValue) |
||||
respMsg.append("\"QRC_VALUE\":\"" + qrcValue + "\","); |
||||
respMsg.append("\"PRINT_SS\":" + ifPrintSS + "}"); |
||||
|
||||
return respMsg.toString(); |
||||
} |
||||
|
||||
public static String createPaymentReversalRequestJsonMsg(String txnId) |
||||
{ |
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"REVERSAL\","); |
||||
respMsg.append("\"TXN_ID\":\"" + txnId + "\"}"); |
||||
|
||||
|
||||
return respMsg.toString(); |
||||
} |
||||
|
||||
public static String createSettlementRequestJsonMsg(boolean ifPrintSS) |
||||
{ |
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"SETTLE\","); |
||||
respMsg.append("\"PRINT_SS\":" + ifPrintSS + "}"); |
||||
|
||||
return respMsg.toString(); |
||||
} |
||||
|
||||
public static String createCardVoidRequestJsonMsg(String txnId, String paymentAppId, String qrcValue, boolean ifPrintSS) |
||||
{ |
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"VOID\","); |
||||
respMsg.append("\"TXN_ID\":\"" + txnId + "\","); |
||||
respMsg.append("\"PAYMENT_APP_ID\":\"" + paymentAppId + "\","); |
||||
if (null != qrcValue) |
||||
respMsg.append("\"QRC_VALUE\":\"" + qrcValue + "\","); |
||||
respMsg.append("\"PRINT_SS\":" + ifPrintSS + "}"); |
||||
|
||||
return respMsg.toString(); |
||||
} |
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,144 @@ |
||||
/** |
||||
* @author slai |
||||
* |
||||
* Created Date: Mar 12, 2005 |
||||
* |
||||
* Copyright 2004 Bank of China Credit Card (International) Ltd. All Rights Reserved. |
||||
* |
||||
* This software is the proprietary information of Bank of China Credit Card (International) Ltd. |
||||
* Use is subject to license terms. |
||||
* |
||||
* Update History: |
||||
* Date Author Changes |
||||
* Mar 12, 2005 slai Document Created |
||||
*/ |
||||
package com.hyweb.n5.eftcore.message.utils; |
||||
|
||||
import java.io.File; |
||||
import java.io.FileInputStream; |
||||
import java.io.IOException; |
||||
import java.security.MessageDigest; |
||||
import java.security.NoSuchAlgorithmException; |
||||
|
||||
|
||||
/* |
||||
* HashUtility.java |
||||
* |
||||
* Class Description: |
||||
* |
||||
*/ |
||||
public class HashUtil { |
||||
protected static final int BUFFER_SIZE = 4096; |
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static String desToHex(byte[] bytes) { |
||||
StringBuffer sb = new StringBuffer(""); |
||||
for (byte b : bytes) { |
||||
String st = String.format("%02X", b); |
||||
sb.append(st); |
||||
} |
||||
return sb.toString(); |
||||
} |
||||
|
||||
public static String getMD5(byte[] data) { |
||||
MessageDigest md = null; |
||||
try { |
||||
md = MessageDigest.getInstance("MD5"); // or SHA(longer)
|
||||
md.update(data); |
||||
return Base64.encodeBytes(md.digest()); |
||||
} catch (NoSuchAlgorithmException e) { |
||||
e.getMessage(); |
||||
e.printStackTrace(); |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
public static String getMD5(File file) { |
||||
MessageDigest md = null; |
||||
FileInputStream fin = null; |
||||
|
||||
byte[] buffer = new byte[BUFFER_SIZE]; |
||||
try { |
||||
md = MessageDigest.getInstance("MD5"); // or SHA(longer)
|
||||
fin = new FileInputStream(file); |
||||
|
||||
int n = 0; |
||||
while (-1 != (n = fin.read(buffer))) { |
||||
md.update(buffer, 0, n); |
||||
} |
||||
return Base64.encodeBytes(md.digest()); |
||||
} catch (NoSuchAlgorithmException e) { |
||||
e.getMessage(); |
||||
e.printStackTrace(); |
||||
} catch (IOException e) { |
||||
e.printStackTrace(); |
||||
} finally { |
||||
try { |
||||
fin.close(); |
||||
} catch (Exception e) { |
||||
} |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
public static String getMD5(String data) { |
||||
MessageDigest md = null; |
||||
try { |
||||
md = MessageDigest.getInstance("MD5"); // or SHA(longer)
|
||||
md.update(data.getBytes()); |
||||
return Base64.encodeBytes(md.digest()); |
||||
} catch (NoSuchAlgorithmException e) { |
||||
e.getMessage(); |
||||
e.printStackTrace(); |
||||
} |
||||
return ""; |
||||
} |
||||
|
||||
public static byte[] getMD5WithoutBase64(String data) { |
||||
MessageDigest md = null; |
||||
try { |
||||
md = MessageDigest.getInstance("MD5"); // or SHA(longer)
|
||||
md.update(data.getBytes()); |
||||
return md.digest(); |
||||
} catch (NoSuchAlgorithmException e) { |
||||
e.getMessage(); |
||||
e.printStackTrace(); |
||||
} |
||||
return new byte[0]; |
||||
} |
||||
|
||||
public static boolean checkMD5(String input, String digest) { |
||||
String base64MD = digest; |
||||
|
||||
String xmlString = input; |
||||
/** |
||||
* Hash the XML message and get the hash value |
||||
*/ |
||||
String xmlMD = getMD5(xmlString); |
||||
/** |
||||
* Message Digest Checking |
||||
*/ |
||||
if (!base64MD.equals(xmlMD)) { |
||||
return false; |
||||
} else |
||||
return true; |
||||
} |
||||
|
||||
public static String getSHA1(String randomNum) { |
||||
String B64 = ""; |
||||
try { |
||||
MessageDigest sha = MessageDigest.getInstance("SHA-1"); |
||||
sha.reset(); |
||||
sha.update(randomNum.getBytes()); |
||||
byte[] pwhash = sha.digest(); |
||||
B64 = Base64.encodeBytes(pwhash); |
||||
} catch (NoSuchAlgorithmException nsae) { |
||||
System.out.println(nsae.getMessage()); |
||||
} |
||||
return B64; |
||||
|
||||
} |
||||
} |
||||
@ -0,0 +1,223 @@ |
||||
package com.hyweb.n5.eftcore.message.utils; |
||||
|
||||
import java.math.BigDecimal; |
||||
import java.math.BigInteger; |
||||
import java.text.CharacterIterator; |
||||
import java.text.StringCharacterIterator; |
||||
import java.util.ArrayList; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
|
||||
|
||||
public class JSONReader { |
||||
private static final Object OBJECT_END = new Object(); |
||||
private static final Object ARRAY_END = new Object(); |
||||
private static final Object COLON = new Object(); |
||||
private static final Object COMMA = new Object(); |
||||
public static final int FIRST = 0; |
||||
public static final int CURRENT = 1; |
||||
public static final int NEXT = 2; |
||||
|
||||
private static Map<Character, Character> escapes = new HashMap<Character, Character>(); |
||||
static { |
||||
escapes.put(Character.valueOf('"'), Character.valueOf('"')); |
||||
escapes.put(Character.valueOf('\\'), Character.valueOf('\\')); |
||||
escapes.put(Character.valueOf('/'), Character.valueOf('/')); |
||||
escapes.put(Character.valueOf('b'), Character.valueOf('\b')); |
||||
escapes.put(Character.valueOf('f'), Character.valueOf('\f')); |
||||
escapes.put(Character.valueOf('n'), Character.valueOf('\n')); |
||||
escapes.put(Character.valueOf('r'), Character.valueOf('\r')); |
||||
escapes.put(Character.valueOf('t'), Character.valueOf('\t')); |
||||
} |
||||
|
||||
private CharacterIterator it; |
||||
private char c; |
||||
private Object token; |
||||
private StringBuffer buf = new StringBuffer(); |
||||
|
||||
private char next() { |
||||
c = it.next(); |
||||
return c; |
||||
} |
||||
|
||||
private void skipWhiteSpace() { |
||||
while (Character.isWhitespace(c)) { |
||||
next(); |
||||
} |
||||
} |
||||
|
||||
public Object read(CharacterIterator ci, int start) { |
||||
it = ci; |
||||
switch (start) { |
||||
case FIRST: |
||||
c = it.first(); |
||||
break; |
||||
case CURRENT: |
||||
c = it.current(); |
||||
break; |
||||
case NEXT: |
||||
c = it.next(); |
||||
break; |
||||
} |
||||
return read(); |
||||
} |
||||
|
||||
public Object read(CharacterIterator it) { |
||||
return read(it, NEXT); |
||||
} |
||||
|
||||
public Object read(String string) { |
||||
return read(new StringCharacterIterator(string), FIRST); |
||||
} |
||||
|
||||
private Object read() { |
||||
skipWhiteSpace(); |
||||
char ch = c; |
||||
next(); |
||||
switch (ch) { |
||||
case '"': token = string(); break; |
||||
case '[': token = array(); break; |
||||
case ']': token = ARRAY_END; break; |
||||
case ',': token = COMMA; break; |
||||
case '{': token = object(); break; |
||||
case '}': token = OBJECT_END; break; |
||||
case ':': token = COLON; break; |
||||
case 't': |
||||
next(); next(); next(); // assumed r-u-e
|
||||
token = Boolean.TRUE; |
||||
break; |
||||
case'f': |
||||
next(); next(); next(); next(); // assumed a-l-s-e
|
||||
token = Boolean.FALSE; |
||||
break; |
||||
case 'n': |
||||
next(); next(); next(); // assumed u-l-l
|
||||
token = null; |
||||
break; |
||||
default: |
||||
c = it.previous(); |
||||
if (Character.isDigit(c) || c == '-') { |
||||
token = number(); |
||||
} |
||||
} |
||||
//logger.debug("token: " + token);
|
||||
System.out.println("token: " + token); // enable this line to see the token stream
|
||||
return token; |
||||
} |
||||
|
||||
private Object object() { |
||||
Map<Object, Object> ret = new HashMap<Object, Object>(); |
||||
Object key = read(); |
||||
while (token != OBJECT_END) { |
||||
read(); // should be a colon
|
||||
if (token != OBJECT_END) { |
||||
ret.put(key, read()); |
||||
if (read() == COMMA) { |
||||
key = read(); |
||||
} |
||||
} |
||||
} |
||||
|
||||
return ret; |
||||
} |
||||
|
||||
private Object array() { |
||||
List<Object> ret = new ArrayList<Object>(); |
||||
Object value = read(); |
||||
while (token != ARRAY_END) { |
||||
ret.add(value); |
||||
if (read() == COMMA) { |
||||
value = read(); |
||||
} |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
private Object number() { |
||||
int length = 0; |
||||
boolean isFloatingPoint = false; |
||||
buf.setLength(0); |
||||
|
||||
if (c == '-') { |
||||
add(); |
||||
} |
||||
length += addDigits(); |
||||
if (c == '.') { |
||||
add(); |
||||
length += addDigits(); |
||||
isFloatingPoint = true; |
||||
} |
||||
if (c == 'e' || c == 'E') { |
||||
add(); |
||||
if (c == '+' || c == '-') { |
||||
add(); |
||||
} |
||||
addDigits(); |
||||
isFloatingPoint = true; |
||||
} |
||||
|
||||
String s = buf.toString(); |
||||
return isFloatingPoint |
||||
? (length < 17) ? (Object)Double.valueOf(s) : new BigDecimal(s) |
||||
: (length < 19) ? (Object)Long.valueOf(s) : new BigInteger(s); |
||||
} |
||||
|
||||
private int addDigits() { |
||||
int ret; |
||||
for (ret = 0; Character.isDigit(c); ++ret) { |
||||
add(); |
||||
} |
||||
return ret; |
||||
} |
||||
|
||||
private Object string() { |
||||
buf.setLength(0); |
||||
while (c != '"') { |
||||
if (c == '\\') { |
||||
next(); |
||||
if (c == 'u') { |
||||
add(unicode()); |
||||
} else { |
||||
Object value = escapes.get(Character.valueOf(c)); |
||||
if (value != null) { |
||||
add(((Character) value).charValue()); |
||||
} |
||||
} |
||||
} else { |
||||
add(); |
||||
} |
||||
} |
||||
next(); |
||||
|
||||
return buf.toString(); |
||||
} |
||||
|
||||
private void add(char cc) { |
||||
buf.append(cc); |
||||
next(); |
||||
} |
||||
|
||||
private void add() { |
||||
add(c); |
||||
} |
||||
|
||||
private char unicode() { |
||||
int value = 0; |
||||
for (int i = 0; i < 4; ++i) { |
||||
switch (next()) { |
||||
case '0': case '1': case '2': case '3': case '4': |
||||
case '5': case '6': case '7': case '8': case '9': |
||||
value = (value << 4) + c - '0'; |
||||
break; |
||||
case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': |
||||
value = (value << 4) + c - 'k'; |
||||
break; |
||||
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': |
||||
value = (value << 4) + c - 'K'; |
||||
break; |
||||
} |
||||
} |
||||
return (char) value; |
||||
} |
||||
} |
||||
@ -0,0 +1,227 @@ |
||||
package com.hyweb.n5.eftcore.test; |
||||
|
||||
import java.text.SimpleDateFormat; |
||||
import java.time.Instant; |
||||
import java.util.Date; |
||||
import java.util.Random; |
||||
import java.util.concurrent.atomic.AtomicInteger; |
||||
|
||||
public class testPackReqMsg { |
||||
private final static int twepoch = 25771200;// 1546272000000L/1000/60;
|
||||
|
||||
/** 序列在id中占的位数 */ |
||||
private final static long sequenceBits = 7L; |
||||
|
||||
/** 时间截向左移7位 */ |
||||
private final static long timestampLeftShift = sequenceBits; |
||||
|
||||
/** 生成序列的掩码,这里为127 */ |
||||
private final static int sequenceMask = -1 ^ (-1 << sequenceBits); |
||||
|
||||
/** 分钟内序列(0~127) */ |
||||
private static int sequence = 0; |
||||
private static int laterSequence = 0; |
||||
|
||||
/** 上次生成ID的时间戳 */ |
||||
private static int lastTimestamp = -1; |
||||
|
||||
private final static MinuteCounter counter = new MinuteCounter(); |
||||
|
||||
/** 预支时间标志位 */ |
||||
static boolean isAdvance = false; |
||||
|
||||
public static String getTxnId() { |
||||
StringBuffer txnId = new StringBuffer(); |
||||
Date date = Date.from(Instant.now()); |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
||||
txnId.append(sdf.format(date)); |
||||
Random random = new Random(date.getTime()); |
||||
for(int i=0; i<3; i++){ |
||||
int r = random.nextInt(10); |
||||
txnId.append(r); |
||||
} |
||||
return txnId.toString(); |
||||
} |
||||
/** |
||||
* 获得下一个ID (该方法是线程安全的) |
||||
* |
||||
* @return SnowflakeId |
||||
*/ |
||||
public static synchronized int nextId() { |
||||
|
||||
|
||||
int timestamp = timeGen(); |
||||
// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
|
||||
if (timestamp < lastTimestamp) { |
||||
throw new RuntimeException(String.format( |
||||
"Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); |
||||
} |
||||
|
||||
if(timestamp > counter.get()) { |
||||
counter.set(timestamp); |
||||
isAdvance = false; |
||||
} |
||||
|
||||
// 如果是同一时间生成的,则进行分钟内序列
|
||||
if (lastTimestamp == timestamp || isAdvance) { |
||||
if(!isAdvance) { |
||||
sequence = (sequence + 1) & sequenceMask; |
||||
} |
||||
|
||||
// 分钟内自增列溢出
|
||||
if (sequence == 0) { |
||||
// 预支下一个分钟,获得新的时间戳
|
||||
isAdvance = true; |
||||
int laterTimestamp = counter.get(); |
||||
if (laterSequence == 0) { |
||||
laterTimestamp = counter.incrementAndGet(); |
||||
} |
||||
|
||||
int nextId = ((laterTimestamp - twepoch) << timestampLeftShift) //
|
||||
| laterSequence; |
||||
laterSequence = (laterSequence + 1) & sequenceMask; |
||||
return nextId; |
||||
} |
||||
} |
||||
// 时间戳改变,分钟内序列重置
|
||||
else { |
||||
sequence = 0; |
||||
laterSequence = 0; |
||||
} |
||||
|
||||
// 上次生成ID的时间截
|
||||
lastTimestamp = timestamp; |
||||
|
||||
// 移位并通过或运算拼到一起组成32位的ID
|
||||
return ((timestamp - twepoch) << timestampLeftShift) //
|
||||
| sequence; |
||||
} |
||||
|
||||
/** |
||||
* 返回以分钟为单位的当前时间 |
||||
* |
||||
* @return 当前时间(分钟) |
||||
*/ |
||||
protected static int timeGen() { |
||||
String timestamp = String.valueOf(System.currentTimeMillis() / 1000 / 60); |
||||
return Integer.valueOf(timestamp); |
||||
} |
||||
|
||||
private static String formatedLine(String lstr,String rstr) |
||||
{ |
||||
int lLen = lstr.length(); |
||||
int rLen = rstr.length(); |
||||
int spLen = 60 - lLen - rLen; |
||||
rstr = String.format("%"+Integer.toString(spLen + rLen)+"s", rstr); |
||||
return lstr + rstr; |
||||
} |
||||
|
||||
public static void main(String[] args) { |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
||||
formatedLine("1234","5678"); |
||||
System.out.println(Instant.now() +"str:" + sdf.format(Date.from(Instant.now()))); |
||||
System.out.println(sdf.format(new Date())); |
||||
System.out.println(System.currentTimeMillis() + "str:" + sdf.format(new Date(System.currentTimeMillis()))); |
||||
System.out.println("0, " +Thread.currentThread().getId()); |
||||
Thread1 thread1 = new Thread1(); |
||||
Thread2 thread2 = new Thread2(); |
||||
Thread3 thread3 = new Thread3(); |
||||
System.out.println("1, " +thread1.getId()); |
||||
System.out.println("2, " +thread2.getId()); |
||||
System.out.println("3, " +thread3.getId()); |
||||
//thread1.run();
|
||||
//thread2.run();
|
||||
//thread3.run();
|
||||
for (int i = 0 ; i < 1000000000 ; i++) |
||||
{ |
||||
System.out.println(i +", " + testPackReqMsg.getTxnId()); |
||||
} |
||||
/*// TODO Auto-generated method stub
|
||||
String txnId = "20190124164613768351"; |
||||
String macKey = "0EAEA18F7A46B9C8765B3DB313267C75"; |
||||
BigDecimal txnAmt = new BigDecimal(13.35); |
||||
boolean ifPrintSS = false; |
||||
BigDecimal tipAmt = null; |
||||
String paymentAppId = ""; |
||||
String qrcValue = null; |
||||
|
||||
StringBuffer respMsg = new StringBuffer(); |
||||
respMsg.append("{\"EVENT_NAME\":\"SALE\","); |
||||
respMsg.append("\"TXN_ID\":\"" + txnId + "\","); |
||||
respMsg.append("\"TXN_AMT\":" + txnAmt + ","); |
||||
if (null != tipAmt) |
||||
respMsg.append("\"TIPS\":" + tipAmt + ","); |
||||
respMsg.append("\"PAYMENT_APP_ID\":\"" + paymentAppId + "\","); |
||||
if (null != qrcValue) |
||||
respMsg.append("\"QRC_VALUE\":\"" + qrcValue + "\","); |
||||
respMsg.append("\"PRINT_SS\":" + ifPrintSS + "}"); |
||||
//{"EVENT_NAME":"SALE","TXN_ID":"20190124164613768351","TXN_AMT":13.35,"PAYMENT_APP_ID":"","PRINT_SS":false}
|
||||
byte[] macMD5Hash = HashUtil.getMD5WithoutBase64(respMsg.toString() + '&' + macKey); |
||||
String macMD5Hex = Utils.toHexString(macMD5Hash, macMD5Hash.length); |
||||
|
||||
N5Message requestMsg = new N5Message(); |
||||
try { |
||||
requestMsg.setBody(respMsg.toString().getBytes("UTF-8")); |
||||
requestMsg.setMac(Utils.readHexString(macMD5Hex)); |
||||
|
||||
byte[] finalRequestMsg = requestMsg.toBytes(); |
||||
} catch (UnsupportedEncodingException e) { |
||||
e.printStackTrace(); |
||||
} |
||||
|
||||
*/ |
||||
} |
||||
} |
||||
|
||||
class MinuteCounter { |
||||
private static final int MASK = 0x7FFFFFFF; |
||||
private final AtomicInteger atom; |
||||
|
||||
public MinuteCounter() { |
||||
atom = new AtomicInteger(0); |
||||
} |
||||
|
||||
public final int incrementAndGet() { |
||||
return atom.incrementAndGet() & MASK; |
||||
} |
||||
|
||||
public int get() { |
||||
return atom.get() & MASK; |
||||
} |
||||
|
||||
public void set(int newValue) { |
||||
atom.set(newValue & MASK); |
||||
} |
||||
} |
||||
class Thread1 extends Thread{ |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
||||
@Override |
||||
public void run() { |
||||
// TODO Auto-generated method stub
|
||||
System.out.println("1, " +sdf.format(new Date())); |
||||
System.out.println("1*" + System.currentTimeMillis()); |
||||
System.out.println("1#" + testPackReqMsg.nextId()); |
||||
} |
||||
} |
||||
|
||||
class Thread2 extends Thread{ |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
||||
@Override |
||||
public void run() { |
||||
// TODO Auto-generated method stub
|
||||
System.out.println("2, " +sdf.format(new Date())); |
||||
System.out.println("2*" + System.currentTimeMillis()); |
||||
System.out.println("2#" + testPackReqMsg.nextId()); |
||||
} |
||||
} |
||||
|
||||
class Thread3 extends Thread{ |
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
||||
@Override |
||||
public void run() { |
||||
// TODO Auto-generated method stub
|
||||
System.out.println("3, " +sdf.format(new Date())); |
||||
System.out.println("3*" + System.currentTimeMillis()); |
||||
System.out.println("3#" + testPackReqMsg.nextId()); |
||||
} |
||||
} |
||||
Loading…
Reference in new issue