This commit is contained in:
duancheng 2024-11-08 15:23:36 +08:00
commit 41e8f2e736
30 changed files with 5347 additions and 0 deletions

2
ysepay/.gitattributes vendored Normal file
View File

@ -0,0 +1,2 @@
/mvnw text eol=lf
*.cmd text eol=crlf

33
ysepay/.gitignore vendored Normal file
View File

@ -0,0 +1,33 @@
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/

View File

@ -0,0 +1,19 @@
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
wrapperVersion=3.3.2
distributionType=only-script
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,7 @@
2024-11-08 11:20:22.744 [http-nio-8080-exec-1] [ERROR] [environmentLogger:110] - autoConfig logback-cfca.xml: WARNNING: [configureByResource] jar:file:/D:/duancheng_java/ysepay/lib/cfca-logback-4.2.1.0.jar!/logback-cfca.xml
2024-11-08 11:23:01.795 [http-nio-8080-exec-1] [ERROR] [environmentLogger:110] - autoConfig logback-cfca.xml: WARNNING: [configureByResource] jar:file:/D:/duancheng_java/ysepay/lib/cfca-logback-4.2.1.0.jar!/logback-cfca.xml
2024-11-08 14:22:29.048 [http-nio-8080-exec-1] [ERROR] [environmentLogger:110] - autoConfig logback-cfca.xml: WARNNING: [configureByResource] jar:file:/D:/duancheng_java/ysepay/lib/cfca-logback-4.2.1.0.jar!/logback-cfca.xml
2024-11-08 14:31:19.683 [http-nio-8080-exec-1] [ERROR] [environmentLogger:110] - autoConfig logback-cfca.xml: WARNNING: [configureByResource] jar:file:/D:/duancheng_java/ysepay/lib/cfca-logback-4.2.1.0.jar!/logback-cfca.xml
2024-11-08 14:37:55.041 [http-nio-8080-exec-1] [ERROR] [environmentLogger:110] - autoConfig logback-cfca.xml: WARNNING: [configureByResource] jar:file:/D:/duancheng_java/ysepay/lib/cfca-logback-4.2.1.0.jar!/logback-cfca.xml
2024-11-08 14:42:00.023 [http-nio-8080-exec-1] [ERROR] [environmentLogger:110] - autoConfig logback-cfca.xml: WARNNING: [configureByResource] jar:file:/D:/duancheng_java/ysepay/lib/cfca-logback-4.2.1.0.jar!/logback-cfca.xml
2024-11-08 15:02:30.317 [http-nio-8080-exec-1] [ERROR] [environmentLogger:110] - autoConfig logback-cfca.xml: WARNNING: [configureByResource] jar:file:/D:/duancheng_java/ysepay/lib/cfca-logback-4.2.1.0.jar!/logback-cfca.xml

File diff suppressed because one or more lines are too long

259
ysepay/mvnw vendored Normal file
View File

@ -0,0 +1,259 @@
#!/bin/sh
# ----------------------------------------------------------------------------
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
# ----------------------------------------------------------------------------
# ----------------------------------------------------------------------------
# Apache Maven Wrapper startup batch script, version 3.3.2
#
# Optional ENV vars
# -----------------
# JAVA_HOME - location of a JDK home dir, required when download maven via java source
# MVNW_REPOURL - repo url base for downloading maven distribution
# MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
# MVNW_VERBOSE - true: enable verbose log; debug: trace the mvnw script; others: silence the output
# ----------------------------------------------------------------------------
set -euf
[ "${MVNW_VERBOSE-}" != debug ] || set -x
# OS specific support.
native_path() { printf %s\\n "$1"; }
case "$(uname)" in
CYGWIN* | MINGW*)
[ -z "${JAVA_HOME-}" ] || JAVA_HOME="$(cygpath --unix "$JAVA_HOME")"
native_path() { cygpath --path --windows "$1"; }
;;
esac
# set JAVACMD and JAVACCMD
set_java_home() {
# For Cygwin and MinGW, ensure paths are in Unix format before anything is touched
if [ -n "${JAVA_HOME-}" ]; then
if [ -x "$JAVA_HOME/jre/sh/java" ]; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
JAVACCMD="$JAVA_HOME/jre/sh/javac"
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACCMD="$JAVA_HOME/bin/javac"
if [ ! -x "$JAVACMD" ] || [ ! -x "$JAVACCMD" ]; then
echo "The JAVA_HOME environment variable is not defined correctly, so mvnw cannot run." >&2
echo "JAVA_HOME is set to \"$JAVA_HOME\", but \"\$JAVA_HOME/bin/java\" or \"\$JAVA_HOME/bin/javac\" does not exist." >&2
return 1
fi
fi
else
JAVACMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v java
)" || :
JAVACCMD="$(
'set' +e
'unset' -f command 2>/dev/null
'command' -v javac
)" || :
if [ ! -x "${JAVACMD-}" ] || [ ! -x "${JAVACCMD-}" ]; then
echo "The java/javac command does not exist in PATH nor is JAVA_HOME set, so mvnw cannot run." >&2
return 1
fi
fi
}
# hash string like Java String::hashCode
hash_string() {
str="${1:-}" h=0
while [ -n "$str" ]; do
char="${str%"${str#?}"}"
h=$(((h * 31 + $(LC_CTYPE=C printf %d "'$char")) % 4294967296))
str="${str#?}"
done
printf %x\\n $h
}
verbose() { :; }
[ "${MVNW_VERBOSE-}" != true ] || verbose() { printf %s\\n "${1-}"; }
die() {
printf %s\\n "$1" >&2
exit 1
}
trim() {
# MWRAPPER-139:
# Trims trailing and leading whitespace, carriage returns, tabs, and linefeeds.
# Needed for removing poorly interpreted newline sequences when running in more
# exotic environments such as mingw bash on Windows.
printf "%s" "${1}" | tr -d '[:space:]'
}
# parse distributionUrl and optional distributionSha256Sum, requires .mvn/wrapper/maven-wrapper.properties
while IFS="=" read -r key value; do
case "${key-}" in
distributionUrl) distributionUrl=$(trim "${value-}") ;;
distributionSha256Sum) distributionSha256Sum=$(trim "${value-}") ;;
esac
done <"${0%/*}/.mvn/wrapper/maven-wrapper.properties"
[ -n "${distributionUrl-}" ] || die "cannot read distributionUrl property in ${0%/*}/.mvn/wrapper/maven-wrapper.properties"
case "${distributionUrl##*/}" in
maven-mvnd-*bin.*)
MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/
case "${PROCESSOR_ARCHITECTURE-}${PROCESSOR_ARCHITEW6432-}:$(uname -a)" in
*AMD64:CYGWIN* | *AMD64:MINGW*) distributionPlatform=windows-amd64 ;;
:Darwin*x86_64) distributionPlatform=darwin-amd64 ;;
:Darwin*arm64) distributionPlatform=darwin-aarch64 ;;
:Linux*x86_64*) distributionPlatform=linux-amd64 ;;
*)
echo "Cannot detect native platform for mvnd on $(uname)-$(uname -m), use pure java version" >&2
distributionPlatform=linux-amd64
;;
esac
distributionUrl="${distributionUrl%-bin.*}-$distributionPlatform.zip"
;;
maven-mvnd-*) MVN_CMD=mvnd.sh _MVNW_REPO_PATTERN=/maven/mvnd/ ;;
*) MVN_CMD="mvn${0##*/mvnw}" _MVNW_REPO_PATTERN=/org/apache/maven/ ;;
esac
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
[ -z "${MVNW_REPOURL-}" ] || distributionUrl="$MVNW_REPOURL$_MVNW_REPO_PATTERN${distributionUrl#*"$_MVNW_REPO_PATTERN"}"
distributionUrlName="${distributionUrl##*/}"
distributionUrlNameMain="${distributionUrlName%.*}"
distributionUrlNameMain="${distributionUrlNameMain%-bin}"
MAVEN_USER_HOME="${MAVEN_USER_HOME:-${HOME}/.m2}"
MAVEN_HOME="${MAVEN_USER_HOME}/wrapper/dists/${distributionUrlNameMain-}/$(hash_string "$distributionUrl")"
exec_maven() {
unset MVNW_VERBOSE MVNW_USERNAME MVNW_PASSWORD MVNW_REPOURL || :
exec "$MAVEN_HOME/bin/$MVN_CMD" "$@" || die "cannot exec $MAVEN_HOME/bin/$MVN_CMD"
}
if [ -d "$MAVEN_HOME" ]; then
verbose "found existing MAVEN_HOME at $MAVEN_HOME"
exec_maven "$@"
fi
case "${distributionUrl-}" in
*?-bin.zip | *?maven-mvnd-?*-?*.zip) ;;
*) die "distributionUrl is not valid, must match *-bin.zip or maven-mvnd-*.zip, but found '${distributionUrl-}'" ;;
esac
# prepare tmp dir
if TMP_DOWNLOAD_DIR="$(mktemp -d)" && [ -d "$TMP_DOWNLOAD_DIR" ]; then
clean() { rm -rf -- "$TMP_DOWNLOAD_DIR"; }
trap clean HUP INT TERM EXIT
else
die "cannot create temp dir"
fi
mkdir -p -- "${MAVEN_HOME%/*}"
# Download and Install Apache Maven
verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
verbose "Downloading from: $distributionUrl"
verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
# select .zip or .tar.gz
if ! command -v unzip >/dev/null; then
distributionUrl="${distributionUrl%.zip}.tar.gz"
distributionUrlName="${distributionUrl##*/}"
fi
# verbose opt
__MVNW_QUIET_WGET=--quiet __MVNW_QUIET_CURL=--silent __MVNW_QUIET_UNZIP=-q __MVNW_QUIET_TAR=''
[ "${MVNW_VERBOSE-}" != true ] || __MVNW_QUIET_WGET='' __MVNW_QUIET_CURL='' __MVNW_QUIET_UNZIP='' __MVNW_QUIET_TAR=v
# normalize http auth
case "${MVNW_PASSWORD:+has-password}" in
'') MVNW_USERNAME='' MVNW_PASSWORD='' ;;
has-password) [ -n "${MVNW_USERNAME-}" ] || MVNW_USERNAME='' MVNW_PASSWORD='' ;;
esac
if [ -z "${MVNW_USERNAME-}" ] && command -v wget >/dev/null; then
verbose "Found wget ... using wget"
wget ${__MVNW_QUIET_WGET:+"$__MVNW_QUIET_WGET"} "$distributionUrl" -O "$TMP_DOWNLOAD_DIR/$distributionUrlName" || die "wget: Failed to fetch $distributionUrl"
elif [ -z "${MVNW_USERNAME-}" ] && command -v curl >/dev/null; then
verbose "Found curl ... using curl"
curl ${__MVNW_QUIET_CURL:+"$__MVNW_QUIET_CURL"} -f -L -o "$TMP_DOWNLOAD_DIR/$distributionUrlName" "$distributionUrl" || die "curl: Failed to fetch $distributionUrl"
elif set_java_home; then
verbose "Falling back to use Java to download"
javaSource="$TMP_DOWNLOAD_DIR/Downloader.java"
targetZip="$TMP_DOWNLOAD_DIR/$distributionUrlName"
cat >"$javaSource" <<-END
public class Downloader extends java.net.Authenticator
{
protected java.net.PasswordAuthentication getPasswordAuthentication()
{
return new java.net.PasswordAuthentication( System.getenv( "MVNW_USERNAME" ), System.getenv( "MVNW_PASSWORD" ).toCharArray() );
}
public static void main( String[] args ) throws Exception
{
setDefault( new Downloader() );
java.nio.file.Files.copy( java.net.URI.create( args[0] ).toURL().openStream(), java.nio.file.Paths.get( args[1] ).toAbsolutePath().normalize() );
}
}
END
# For Cygwin/MinGW, switch paths to Windows format before running javac and java
verbose " - Compiling Downloader.java ..."
"$(native_path "$JAVACCMD")" "$(native_path "$javaSource")" || die "Failed to compile Downloader.java"
verbose " - Running Downloader.java ..."
"$(native_path "$JAVACMD")" -cp "$(native_path "$TMP_DOWNLOAD_DIR")" Downloader "$distributionUrl" "$(native_path "$targetZip")"
fi
# If specified, validate the SHA-256 sum of the Maven distribution zip file
if [ -n "${distributionSha256Sum-}" ]; then
distributionSha256Result=false
if [ "$MVN_CMD" = mvnd.sh ]; then
echo "Checksum validation is not supported for maven-mvnd." >&2
echo "Please disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
elif command -v sha256sum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | sha256sum -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
elif command -v shasum >/dev/null; then
if echo "$distributionSha256Sum $TMP_DOWNLOAD_DIR/$distributionUrlName" | shasum -a 256 -c >/dev/null 2>&1; then
distributionSha256Result=true
fi
else
echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available." >&2
echo "Please install either command, or disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." >&2
exit 1
fi
if [ $distributionSha256Result = false ]; then
echo "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised." >&2
echo "If you updated your Maven version, you need to update the specified distributionSha256Sum property." >&2
exit 1
fi
fi
# unzip and move
if command -v unzip >/dev/null; then
unzip ${__MVNW_QUIET_UNZIP:+"$__MVNW_QUIET_UNZIP"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -d "$TMP_DOWNLOAD_DIR" || die "failed to unzip"
else
tar xzf${__MVNW_QUIET_TAR:+"$__MVNW_QUIET_TAR"} "$TMP_DOWNLOAD_DIR/$distributionUrlName" -C "$TMP_DOWNLOAD_DIR" || die "failed to untar"
fi
printf %s\\n "$distributionUrl" >"$TMP_DOWNLOAD_DIR/$distributionUrlNameMain/mvnw.url"
mv -- "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" "$MAVEN_HOME" || [ -d "$MAVEN_HOME" ] || die "fail to move MAVEN_HOME"
clean || :
exec_maven "$@"

149
ysepay/mvnw.cmd vendored Normal file
View File

@ -0,0 +1,149 @@
<# : batch portion
@REM ----------------------------------------------------------------------------
@REM Licensed to the Apache Software Foundation (ASF) under one
@REM or more contributor license agreements. See the NOTICE file
@REM distributed with this work for additional information
@REM regarding copyright ownership. The ASF licenses this file
@REM to you under the Apache License, Version 2.0 (the
@REM "License"); you may not use this file except in compliance
@REM with the License. You may obtain a copy of the License at
@REM
@REM http://www.apache.org/licenses/LICENSE-2.0
@REM
@REM Unless required by applicable law or agreed to in writing,
@REM software distributed under the License is distributed on an
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@REM KIND, either express or implied. See the License for the
@REM specific language governing permissions and limitations
@REM under the License.
@REM ----------------------------------------------------------------------------
@REM ----------------------------------------------------------------------------
@REM Apache Maven Wrapper startup batch script, version 3.3.2
@REM
@REM Optional ENV vars
@REM MVNW_REPOURL - repo url base for downloading maven distribution
@REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven
@REM MVNW_VERBOSE - true: enable verbose log; others: silence the output
@REM ----------------------------------------------------------------------------
@IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0)
@SET __MVNW_CMD__=
@SET __MVNW_ERROR__=
@SET __MVNW_PSMODULEP_SAVE=%PSModulePath%
@SET PSModulePath=
@FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @(
IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B)
)
@SET PSModulePath=%__MVNW_PSMODULEP_SAVE%
@SET __MVNW_PSMODULEP_SAVE=
@SET __MVNW_ARG0_NAME__=
@SET MVNW_USERNAME=
@SET MVNW_PASSWORD=
@IF NOT "%__MVNW_CMD__%"=="" (%__MVNW_CMD__% %*)
@echo Cannot start maven from wrapper >&2 && exit /b 1
@GOTO :EOF
: end batch / begin powershell #>
$ErrorActionPreference = "Stop"
if ($env:MVNW_VERBOSE -eq "true") {
$VerbosePreference = "Continue"
}
# calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties
$distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl
if (!$distributionUrl) {
Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties"
}
switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) {
"maven-mvnd-*" {
$USE_MVND = $true
$distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip"
$MVN_CMD = "mvnd.cmd"
break
}
default {
$USE_MVND = $false
$MVN_CMD = $script -replace '^mvnw','mvn'
break
}
}
# apply MVNW_REPOURL and calculate MAVEN_HOME
# maven home pattern: ~/.m2/wrapper/dists/{apache-maven-<version>,maven-mvnd-<version>-<platform>}/<hash>
if ($env:MVNW_REPOURL) {
$MVNW_REPO_PATTERN = if ($USE_MVND) { "/org/apache/maven/" } else { "/maven/mvnd/" }
$distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace '^.*'+$MVNW_REPO_PATTERN,'')"
}
$distributionUrlName = $distributionUrl -replace '^.*/',''
$distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$',''
$MAVEN_HOME_PARENT = "$HOME/.m2/wrapper/dists/$distributionUrlNameMain"
if ($env:MAVEN_USER_HOME) {
$MAVEN_HOME_PARENT = "$env:MAVEN_USER_HOME/wrapper/dists/$distributionUrlNameMain"
}
$MAVEN_HOME_NAME = ([System.Security.Cryptography.MD5]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join ''
$MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME"
if (Test-Path -Path "$MAVEN_HOME" -PathType Container) {
Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME"
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"
exit $?
}
if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) {
Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl"
}
# prepare tmp dir
$TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile
$TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir"
$TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null
trap {
if ($TMP_DOWNLOAD_DIR.Exists) {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
}
New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null
# Download and Install Apache Maven
Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..."
Write-Verbose "Downloading from: $distributionUrl"
Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName"
$webclient = New-Object System.Net.WebClient
if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) {
$webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD)
}
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
$webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null
# If specified, validate the SHA-256 sum of the Maven distribution zip file
$distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum
if ($distributionSha256Sum) {
if ($USE_MVND) {
Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties."
}
Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash
if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) {
Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property."
}
}
# unzip and move
Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null
Rename-Item -Path "$TMP_DOWNLOAD_DIR/$distributionUrlNameMain" -NewName $MAVEN_HOME_NAME | Out-Null
try {
Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null
} catch {
if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) {
Write-Error "fail to move MAVEN_HOME"
}
} finally {
try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null }
catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" }
}
Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD"

130
ysepay/pom.xml Normal file
View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.3.5</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.yeledui</groupId>
<artifactId>ysePay</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>ysePay</name>
<description>ysePay</description>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.12</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
<dependency>
<groupId>commons-httpclient</groupId>
<artifactId>commons-httpclient</artifactId>
<version>3.1</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.14.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpmime</artifactId>
<version>4.5.13</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.6.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.21.1</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.cfca</groupId>
<artifactId>logback-cfca-jdk1.6</artifactId>
<version>4.1.1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/cfca-logback-4.2.1.0.jar</systemPath>
</dependency>
<dependency>
<groupId>cfca-sadk</groupId>
<artifactId>cfca-sadk</artifactId>
<version>3.6.2.1</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/cfca-sadk-3.6.2.1.jar</systemPath>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.32</version>
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>22</source>
<target>22</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,13 @@
package com.yeledui.ysepay;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class YsepayApplication {
public static void main(String[] args) {
SpringApplication.run(YsepayApplication.class, args);
}
}

View File

@ -0,0 +1,42 @@
package com.yeledui.ysepay;
import org.springframework.web.bind.annotation.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import com.yeledui.ysepay.utils.*;
@RestController
public class payController {
@PostMapping("/pay")
public String pay(@RequestBody JSONObject json) throws Exception {
System.out.println("收到json:"+json);
String HTTP_URL = "https://qrcode.ysepay.com/gateway.do";
Map<String,String> commonMap = new HashMap<String,String>();
commonMap.put("method",json.getString("method"));
commonMap.put("partner_id",json.getString("partner_id"));
commonMap.put("timestamp",json.getString("timestamp"));
commonMap.put("charset",json.getString("charset"));
commonMap.put("sign_type",json.getString("sign_type"));
// commonMap.put("sign",json.getString("sign"));
commonMap.put("notify_url",json.getString("notify_url"));
commonMap.put("version",json.getString("version"));
commonMap.put("biz_content",json.getString("biz_content"));
String sign = YsPaySignUtils.sign(commonMap);
commonMap.put("sign",sign);
commonMap.put("biz_content", URLEncoder.encode(commonMap.get("biz_content"),"utf-8"));
System.out.println("commonMap = "+commonMap.toString());
String result = HttpRequestUtil.sendPost(HTTP_URL, Utils.mapToString(commonMap)); //发送请求
JSONObject jsonObject=JSONObject.parseObject(result);
String respString =jsonObject.toString();
System.out.println("收到银盛的应答:"+respString);
return respString;
}
}

View File

@ -0,0 +1,6 @@
package com.yeledui.ysepay;
public class resp {
public String sign;
public String biz_content;
}

View File

@ -0,0 +1,46 @@
package com.yeledui.ysepay.utils;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class AESUtil {
/**
* 加密
*
* @param content 需要加密的内容
* @param password 加密密钥
* @return
*/
public static byte[] encrypt(byte[] content, byte[] password) throws Exception {
try {
SecretKeySpec key = new SecretKeySpec(password,"AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return result; // 加密
} catch (Exception e) {
throw e;
}
}
/**解密
* @param content 待解密内容
* @param password 解密密钥
* @return
* @throws Exception
*/
public static byte[] decrypt(byte[] content, byte[] password) throws Exception {
try {
SecretKeySpec key = new SecretKeySpec(password,"AES");
Cipher cipher = Cipher.getInstance("AES");// 创建密码器
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
byte[] result = cipher.doFinal(content);
return result; // 解密
} catch (Exception e) {
throw e;
}
}
}

View File

@ -0,0 +1,503 @@
package com.yeledui.ysepay.utils;
import java.io.ByteArrayOutputStream;
public class ByteUtil {
private static String hexStr = "0123456789ABCDEF";
private static final char[] BToA = "0123456789abcdef".toCharArray();
private static final String N_LINE = "----------------------------------------------------------------------------";
/**
* 二进制
*/
private static final int DECIMAL = 2;
/**
* @param iSource
* @param iArrayLen
* @return
*/
public static byte[] int2ByteArray(int iSource, int iArrayLen) {
byte[] bLocalArr = new byte[iArrayLen];
for (int i = iArrayLen; (i < 4) && (i > 0); i--) {
bLocalArr[i - 1] = (byte) (iSource >> 8 * (iArrayLen - i) & 0xFF);
}
return bLocalArr;
}
public static String trace(byte[] inBytes) {
int i, j = 0;
byte[] temp = new byte[76];
bytesSet(temp, ' ');
StringBuffer strc = new StringBuffer("");
strc.append(N_LINE + "\n");
for (i = 0; i < inBytes.length; i++) {
if (j == 0) {
System.arraycopy(String.format("%03d: ", i).getBytes(), 0,
temp, 0, 5);
System.arraycopy(String.format(":%03d", i + 15).getBytes(), 0,
temp, 72, 4);
}
System.arraycopy(String.format("%02X ", inBytes[i]).getBytes(), 0,
temp, j * 3 + 5 + (j > 7 ? 1 : 0), 3);
if (inBytes[i] == 0x00) {
temp[j + 55 + ((j > 7 ? 1 : 0))] = '.';
} else {
temp[j + 55 + ((j > 7 ? 1 : 0))] = inBytes[i];
}
j++;
if (j == 16) {
strc.append(new String(temp)).append("\n");
bytesSet(temp, ' ');
j = 0;
}
}
if (j != 0) {
strc.append(new String(temp)).append("\n");
bytesSet(temp, ' ');
}
strc.append(N_LINE + "\n");
return strc.toString();
}
/**
* byte数组赋值
*
* @param inBytes
* @param fill
* @return
* @throws Exception
*/
private static void bytesSet(byte[] inBytes, char fill) {
if (inBytes.length == 0) {
return;
}
for (int i = 0; i < inBytes.length; i++) {
inBytes[i] = (byte) fill;
}
}
public static byte[] byteAndByte(byte[] begin, byte[] second) {
if (begin == null || begin.length == 0) {
if (second != null && second.length != 0) {
return second;
} else {
return null;
}
} else if (second == null || second.length == 0) {
return begin;
}
byte[] newTotal = new byte[begin.length + second.length];
for (int i = 0; i < begin.length; i++) {
newTotal[i] = begin[i];
}
for (int i = begin.length; i < second.length + begin.length; i++) {
newTotal[i] = second[i - begin.length];
}
return newTotal;
}
public static byte[] getsubByte(byte[] total, int begin, int length) {
if (length > 0) {
byte[] newTotal = new byte[length];
for (int i = begin; i < length + begin; i++) {
newTotal[i - begin] = total[i];
}
return newTotal;
}
return new byte[0];
}
public static String fillString(String string, char filler,int totalLength, boolean atEnd) {
byte[] tempbyte = string.getBytes();
int currentLength = tempbyte.length;
int delta = totalLength - currentLength;
for (int i = 0; i < delta; i++) {
if (atEnd) {
string += filler;
} else {
string = filler + string;
}
}
return string;
}
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || hexString.equals("")) {
return null;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i++) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]) & 0xff);
}
return d;
}
public static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString().toUpperCase();
}
public static String bytesToString(byte[] src, int begin, int length) {
String str1 = null;
StringBuilder sb = new StringBuilder("");
if (begin == 0 && length == 0) {
for (byte element : src) {
sb.append(String.valueOf(element));
}
} else {
for (int i = begin; i < begin + length; i++) {
byte element = src[i];
sb.append(String.valueOf(element));
}
}
str1 = sb.toString();
return str1;
}
/**
* @param bytes
* @return 将二进制转换为十六进制字符输出
*/
public static String binaryToHexString(byte[] bytes) {
String result = "";
String hex = "";
for (int i = 0; i < bytes.length; i++) {
// 字节高4位
hex = String.valueOf(hexStr.charAt((bytes[i] & 0xF0) >> 4));
// 字节低4位
hex += String.valueOf(hexStr.charAt(bytes[i] & 0x0F));
result += hex;
}
return result.toUpperCase();
}
/*
* 二进制数转换到十进制数
*/
public static String binaryToDecimal(String binary) {
StringBuffer buf = new StringBuffer();
String[] strBinary = binary.split(" ");// 根据空格拆分二进制数
for (String str : strBinary) {// 提取二进制数
StringBuffer strBuf = new StringBuffer(str);
char[] element = strBuf.reverse().toString().toCharArray();// 反转二进制数方便运算
int digit = 0;// 次幕
int result = 0;// 结果
for (char temp : element) {// 提取单个数
int intNumber = Integer.parseInt(Character.toString(temp));
intNumber = intNumber * (int) (Math.pow(DECIMAL, digit));// 根据位数算结果
// 算法位数*2的次幕
result = result + intNumber;
digit = digit + 1;// 次幕加一
}
buf.append(result);
buf.append(" ");
}
return buf.toString();
}
/**
* 转化十六进制编码为字符串
* 没有设置编码格式
*/
public static String toStringHex(String s) {
byte[] baKeyword = new byte[s.length() / 2];
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(
i * 2, i * 2 + 2), 16));
} catch (Exception e) {
e.printStackTrace();
}
}
try {
s = new String(baKeyword, "utf-8");// UTF-16le:Not
} catch (Exception e1) {
e1.printStackTrace();
}
return s;
}
/**
* 转化十六进制编码为字符串
* 设置编码格式
*/
public static String toStringHex(String s, String charset) {
byte[] baKeyword = new byte[s.length() / 2];
for (int i = 0; i < baKeyword.length; i++) {
try {
baKeyword[i] = (byte) (0xff & Integer.parseInt(s.substring(
i * 2, i * 2 + 2), 16));
} catch (Exception e) {
e.printStackTrace();
}
}
try {
s = new String(baKeyword, charset);
} catch (Exception e1) {
e1.printStackTrace();
}
return s;
}
/**
* @函数功能: BCD码转为10进制串(阿拉伯数据)
* @输入参数: BCD码
* @输入参数: format 补码方式 true : 前补零 ; false : 后补零
* @输入参数: length 原长度
* @输出结果: 10进制串
*/
public static String cbcd2string(byte[] bytes, boolean format, int length) {
StringBuffer temp = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
temp.append((byte) ((bytes[i] & 0xf0) >>> 4));
temp.append((byte) (bytes[i] & 0x0f));
}
String val = temp.toString();
// 左去零
if (format) {
if (val.length() > length) {
return val.substring(0, 1).equalsIgnoreCase("0") ? val.substring(1) : val;
} else {
return val;
}
}
// 右去零
else {
if (val.length() > length) {
return val.substring(val.length() - 1, val.length()).equalsIgnoreCase("0") ? val.substring(0, val.length() - 1) : val;
} else {
return val;
}
}
}
/**
* @函数功能: 10进制串转为BCD码
* @输入参数: 10进制串
* @输入参数: format 补码方式 true : 前补零 ; false : 后补零
* @输出结果: BCD码
*/
public static byte[] str2cbcd(String asc, boolean format) {
int len = asc.length();
int mod = len % 2;
if (mod != 0) {
if (format) {
asc = "0" + asc;
len = asc.length();
} else {
asc = asc + "0";
len = asc.length();
}
}
byte abt[] = new byte[len];
if (len >= 2) {
len = len / 2;
}
byte bbt[] = new byte[len];
abt = asc.getBytes();
int j, k;
for (int p = 0; p < asc.length() / 2; p++) {
if ((abt[2 * p] >= '0') && (abt[2 * p] <= '9')) {
j = abt[2 * p] - '0';
} else if ((abt[2 * p] >= 'a') && (abt[2 * p] <= 'z')) {
j = abt[2 * p] - 'a' + 0x0a;
} else {
j = abt[2 * p] - 'A' + 0x0a;
}
if ((abt[2 * p + 1] >= '0') && (abt[2 * p + 1] <= '9')) {
k = abt[2 * p + 1] - '0';
} else if ((abt[2 * p + 1] >= 'a') && (abt[2 * p + 1] <= 'z')) {
k = abt[2 * p + 1] - 'a' + 0x0a;
} else {
k = abt[2 * p + 1] - 'A' + 0x0a;
}
int a = (j << 4) + k;
byte b = (byte) a;
bbt[p] = b;
}
return bbt;
}
/**
* @函数功能: 16进制串转为BCD码
* @输入参数: 16进制串
* @输入参数: format 补码方式 true : 前补零 ; false : 后补零
* @输出结果: BCD码
*/
public static byte[] str2Bcd(String s, boolean format) {
if (s.length() % 2 != 0) {
if (format) {
s = "0" + s;
} else {
s = s + "0";
}
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
char[] cs = s.toCharArray();
for (int i = 0; i < cs.length; i += 2) {
int high = cs[i] - '0';
if (high > 9) {
high = high - ('A' - '9' - 1);
}
int low = cs[i + 1] - '0';
if (low > 9) {
low = low - ('A' - '9' - 1);
}
baos.write(high << 4 | low);
}
return baos.toByteArray();
}
/**
* @函数功能: BCD码转为十六进制串
* @输入参数: BCD码
* @输入参数: format 补码方式 true : 前补零 ; false : 后补零
* @输入参数: length 原长度
* @输出结果: 10进制串
*/
public static String bcd2Str(byte[] b, boolean format, int length) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < b.length; i++) {
int h = ((b[i] & 0xff) >> 4) + '0';
if (h > '9') {
h = h + ('A' - '9' - 1);
}
sb.append((char) h);
int l = (b[i] & 0x0f) + '0';
if (l > '9') {
l = l + ('A' - '9' - 1);
}
sb.append((char) l);
}
String val = sb.toString().toUpperCase();
// 左去零
if (format) {
if (val.length() > length) {
return val.substring(0, 1).equalsIgnoreCase("0") ? val.substring(1) : val;
} else {
return val;
}
}
// 右去零
else {
if (val.length() > length) {
return val.substring(val.length() - 1, val.length()).equalsIgnoreCase("0") ? val.substring(0, val.length() - 1) : val;
} else {
return val;
}
}
}
/**
* @函数功能: BCD码转ASC码
* @输入参数: BCD串
* @输出结果: ASC码
*/
public static String bcd2ASC(byte[] bytes) {
StringBuffer temp = new StringBuffer(bytes.length * 2);
for (int i = 0; i < bytes.length; i++) {
int h = ((bytes[i] & 0xf0) >>> 4);
int l = (bytes[i] & 0x0f);
temp.append(BToA[h]).append(BToA[l]);
}
return temp.toString().toUpperCase();
}
// 转化字符串为十六进制编码
public static String toHexString(String s) {
String str = "";
for (int i = 0; i < s.length(); i++) {
int ch = s.charAt(i);
String s4 = Integer.toHexString(ch);
str = str + s4;
}
return str;
}
public static byte[] byteTobyte(byte[] data, int index, int lenth) {
byte[] b = new byte[lenth];
for (int i = index; i < index + lenth; i++) {
b[i - index] = data[i];
}
return b;
}
public static byte[] replenishByteTo8(byte[] b) {
int i = b.length;
int x = i % 8;
if (x != 0) {
x = 8 - x;
String replenish = "";
for (int j = 0; j < x; j++) {
replenish += "FF";
}
return byteAndByte(b, hexStringToBytes(replenish));
} else {
return b;
}
}
public static byte[] replenishByteTo16(byte[] b) {
int i = b.length;
int x = i % 16;
if (x != 0) {
x = 16 - x;
String replenish = "";
for (int j = 0; j < x; j++) {
replenish += "FF";
}
return byteAndByte(b, hexStringToBytes(replenish));
} else {
return b;
}
}
}

View File

@ -0,0 +1,85 @@
package com.yeledui.ysepay.utils;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
/**
* 字符集工具类
*
* @author gientech
*/
public class CharsetKit
{
/** ISO-8859-1 */
public static final String ISO_8859_1 = "ISO-8859-1";
/** UTF-8 */
public static final String UTF_8 = "UTF-8";
/** GBK */
public static final String GBK = "GBK";
/** ISO-8859-1 */
public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
/** UTF-8 */
public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
/** GBK */
public static final Charset CHARSET_GBK = Charset.forName(GBK);
/**
* 转换为Charset对象
*
* @param charset 字符集为空则返回默认字符集
* @return Charset
*/
public static Charset charset(String charset)
{
return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, String srcCharset, String destCharset)
{
return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
}
/**
* 转换字符串的字符集编码
*
* @param source 字符串
* @param srcCharset 源字符集默认ISO-8859-1
* @param destCharset 目标字符集默认UTF-8
* @return 转换后的字符集
*/
public static String convert(String source, Charset srcCharset, Charset destCharset)
{
if (null == srcCharset)
{
srcCharset = StandardCharsets.ISO_8859_1;
}
if (null == destCharset)
{
destCharset = StandardCharsets.UTF_8;
}
if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
{
return source;
}
return new String(source.getBytes(srcCharset), destCharset);
}
/**
* @return 系统字符集编码
*/
public static String systemCharset()
{
return Charset.defaultCharset().name();
}
}

View File

@ -0,0 +1,161 @@
package com.yeledui.ysepay.utils;
/**
* 通用常量信息
*
* @author gientech
*/
public class Constants
{
/**
* UTF-8 字符集
*/
public static final String UTF8 = "UTF-8";
/**
* GBK 字符集
*/
public static final String GBK = "GBK";
/**
* http请求
*/
public static final String HTTP = "http://";
/**
* https请求
*/
public static final String HTTPS = "https://";
/**
* 通用成功标识
*/
public static final String SUCCESS = "0";
/**
* 通用失败标识
*/
public static final String FAIL = "1";
/**
* 登录成功
*/
public static final String LOGIN_SUCCESS = "Success";
/**
* 注销
*/
public static final String LOGOUT = "Logout";
/**
* 注册
*/
public static final String REGISTER = "Register";
/**
* 登录失败
*/
public static final String LOGIN_FAIL = "Error";
/**
* 验证码 redis key
*/
public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
/**
* 登录用户 redis key
*/
public static final String LOGIN_TOKEN_KEY = "login_tokens:";
/**
* 防重提交 redis key
*/
public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
/**
* 限流 redis key
*/
public static final String RATE_LIMIT_KEY = "rate_limit:";
/**
* 验证码有效期分钟
*/
public static final Integer CAPTCHA_EXPIRATION = 2;
/**
* 令牌
*/
public static final String TOKEN = "token";
/**
* 令牌前缀
*/
public static final String TOKEN_PREFIX = "Bearer ";
/**
* 令牌前缀
*/
public static final String LOGIN_USER_KEY = "login_user_key";
/**
* 用户ID
*/
public static final String JWT_USERID = "userid";
/**
* 用户头像
*/
public static final String JWT_AVATAR = "avatar";
/**
* 创建时间
*/
public static final String JWT_CREATED = "created";
/**
* 用户权限
*/
public static final String JWT_AUTHORITIES = "authorities";
/**
* 参数管理 cache key
*/
public static final String SYS_CONFIG_KEY = "sys_config:";
/**
* 字典管理 cache key
*/
public static final String SYS_DICT_KEY = "sys_dict:";
/**
* 资源映射路径 前缀
*/
public static final String RESOURCE_PREFIX = "/profile";
/**
* RMI 远程方法调用
*/
public static final String LOOKUP_RMI = "rmi:";
/**
* LDAP 远程方法调用
*/
public static final String LOOKUP_LDAP = "ldap:";
/**
* LDAPS 远程方法调用
*/
public static final String LOOKUP_LDAPS = "ldaps:";
/**
* 定时任务白名单配置仅允许访问的包名如其他需要可以自行添加
*/
public static final String[] JOB_WHITELIST_STR = { "com.gientech" };
/**
* 定时任务违规的字符
*/
public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
"org.springframework", "org.apache", "com.gientech.common.utils.file" };
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,89 @@
package com.yeledui.ysepay.utils;
import cfca.sadk.algorithm.sm2.SM2PublicKey;
import cfca.sadk.org.bouncycastle.jce.provider.BouncyCastleProvider;
import cfca.sadk.x509.certificate.X509Cert;
import java.io.FileInputStream;
import java.io.Serializable;
import java.security.PublicKey;
import java.security.Security;
public class GMCertInfo implements Serializable
{
private static final long serialVersionUID = 1L;
private SM2PublicKey pubKeySM2;
private PublicKey pubKey;
private byte[] priKey;
private X509Cert x509Cert;
//读取原始公钥
public static byte[] ReadPublicKeyFromRaw(String publickeyFile) throws Exception
{
FileInputStream br = new FileInputStream(publickeyFile);
byte[] b1 = new byte[2000];
int k = br.read(b1);
byte[] b = new byte[k];
System.arraycopy(b1, 0, b, 0, k);
return b;
}
// 从X509证书文件读取公钥,Certificate只含有公钥
// .crt .cer文件都可以读取 .cer是IE导出的公钥证书der格式
// -----BEGIN CERTIFICATE-----开始 文件头不许有其它内容
// -----END CERTIFICATE-----
// cer公钥证书 二进制
public void ReadPublicKeyFromX509CertificateSM2(String cerFilePath) throws Exception
{
Security.addProvider(new BouncyCastleProvider());
byte[] cer = ReadPublicKeyFromRaw(cerFilePath);
ReadPublicKeyFromX509CertificateSM2(cer);
}
public void ReadPublicKeyFromX509CertificateSM2(byte[] cer) throws Exception
{
Security.addProvider(new BouncyCastleProvider());
x509Cert = new X509Cert(cer);
//获取公钥对象
pubKeySM2 = (SM2PublicKey) x509Cert.getPublicKey();
pubKey = x509Cert.getPublicKey();
}
public SM2PublicKey getPubKeySM2() {
return pubKeySM2;
}
public void setPubKeySM2(SM2PublicKey pubKeySM2) {
this.pubKeySM2 = pubKeySM2;
}
public PublicKey getPubKey() {
return pubKey;
}
public void setPubKey(PublicKey pubKey) {
this.pubKey = pubKey;
}
public byte[] getPriKey() {
return priKey;
}
public void setPriKey(byte[] priKey) {
this.priKey = priKey;
}
public X509Cert getX509Cert() {
return x509Cert;
}
public void setX509Cert(X509Cert x509Cert) {
this.x509Cert = x509Cert;
}
}

View File

@ -0,0 +1,197 @@
package com.yeledui.ysepay.utils;
import cfca.sadk.algorithm.common.Mechanism;
import cfca.sadk.algorithm.sm2.SM2PublicKey;
import cfca.sadk.lib.crypto.JCrypto;
import cfca.sadk.lib.crypto.Session;
import cfca.sadk.util.EnvelopeUtil;
import cfca.sadk.util.KeyUtil;
import cfca.sadk.util.Signature;
import cfca.sadk.x509.certificate.X509Cert;
import java.security.PrivateKey;
import java.util.*;
/**
* @类名称GMSignUtil
* @类描述国密算法SM2签名工具类
* @作者zhanggy
* @日期2021年8月11日
*/
public class GMSignUtils {
/**
* 国密算法数据加密(SM2公钥加密长度通常限定为136字节内)
* @param src
* @param data
* @throws Exception
*/
public static String encryptData(String src,String data) throws Exception {
String encryptMsg = null;
GMCertInfo certInfo = getVerifyCertInfo(src);
try {
final String deviceName = JCrypto.JSOFT_LIB;
JCrypto.getInstance().initialize(deviceName, null);
final Session session = JCrypto.getInstance().openSession(deviceName);
// 一个或者多个加密证书
X509Cert[] recvcerts = new X509Cert[] { certInfo.getX509Cert() };
byte[] base64Bytes = EnvelopeUtil.envelopeMessage(data.getBytes("UTF-8"), Mechanism.SM4_ECB, recvcerts, session);
encryptMsg = new String(base64Bytes);
} catch (Exception e) {
throw new Exception("数据SM2加密失败");
}
return encryptMsg;
}
/**
* 获取支付平台公钥证书
* @param src
* @return
* @throws Exception
*/
public static GMCertInfo getVerifyCertInfo(String src) throws Exception {
GMCertInfo certInfo = new GMCertInfo();
try{
certInfo.ReadPublicKeyFromX509CertificateSM2(src);
} catch (Exception e) {
throw new Exception("银盛平台公钥证书加载失败");
}
return certInfo;
}
/**
* 加载公钥证书
* @return
*
*/
public synchronized static GMCertInfo initValidateCert(byte[] bs,String certId) {
GMCertInfo certInfo = new GMCertInfo();
try {
certInfo.ReadPublicKeyFromX509CertificateSM2(bs);
return certInfo;
} catch (Exception e) {
System.out.println("银盛平台公钥证书加载失败"+ e);
}
return certInfo;
}
/**
* 国密算法验证签名报文
* @param certInfo
* @param bcheck
* @param xmlMsg
* @throws Exception
*/
public static boolean verifyMsgSignSM2(GMCertInfo certInfo, byte[] bcheck, byte[] xmlMsg){
boolean bFlag;
try{
SM2PublicKey pubKey = certInfo.getPubKeySM2();
final String deviceName = JCrypto.JSOFT_LIB;
JCrypto.getInstance().initialize(deviceName, null);
Session session = JCrypto.getInstance().openSession(deviceName);
final Signature util = new Signature();
final String signAlg = Mechanism.SM3_SM2;//SM3WithSM2
// 校验必须指定签名算法
bFlag = util.p1VerifyMessage(signAlg,xmlMsg,bcheck,pubKey,session);
} catch (Exception e) {
bFlag = false;
System.out.println("国密验签失败"+e);
}
return bFlag;
}
/**
* 国密算法签名报文
* @param certInfo
* @param msg
* @return 返回 256长度base64编码
* @throws Exception
*/
public synchronized static String signMsgSM2(GMCertInfo certInfo, String msg) {
// 返回的是256位
byte[] signed = new byte[0];
try {
final String deviceName = JCrypto.JSOFT_LIB;
JCrypto.getInstance().initialize(deviceName, null);
Session session = JCrypto.getInstance().openSession(deviceName);
PrivateKey priKey = KeyUtil.getPrivateKeyFromSM2(certInfo.getPriKey(),"YSEPAY_SM2_PWD");
byte[] sourceData = msg.getBytes();
Signature util = new Signature();
String signAlg = Mechanism.SM3_SM2;//SM3WithSM2
// 签名必须指定签名算法返回BASE64签名结果
signed = util.p1SignMessage(signAlg, sourceData, priKey, session);
} catch (Exception e) {
System.out.println("国密报文SM2签名失败"+ e);
}
String checkValue = new String(signed);
return String.format("%-256s", checkValue);
}
/**
* 获取商户私钥证书
* @param src
* @return
* @throws Exception
*/
public synchronized static GMCertInfo getSignCertInfo(String src) throws Exception {
//商户私钥证书
String certfile = src;
GMCertInfo certInfo = new GMCertInfo();
try {
byte[] priKeySm2 = TextFileHelper.readFile(certfile);
certInfo.setPriKey(priKeySm2);
} catch (Exception e) {
throw new Exception("商户签名证书加载失败");
}
return certInfo;
}
/**
* 国密算法签名报文
* @return 返回 256长度base64编码
* @throws Exception
*/
public synchronized static String signMsgSM2(String sm2FilePath,String passWord, String msg) throws Exception {
GMCertInfo certInfo = getSignCertInfo(sm2FilePath);
// 返回的是256位
byte[] signed;
try {
final String deviceName = JCrypto.JSOFT_LIB;
JCrypto.getInstance().initialize(deviceName, null);
Session session = JCrypto.getInstance().openSession(deviceName);
PrivateKey priKey = KeyUtil.getPrivateKeyFromSM2(certInfo.getPriKey(),passWord);
// PrivateKey priKey = KeyUtil.getPrivateKeyFromSM2(certInfo.getPriKey(),"ys123456");
byte[] sourceData = msg.getBytes();
Signature util = new Signature();
String signAlg = Mechanism.SM3_SM2;//SM3WithSM2
// 签名必须指定签名算法返回BASE64签名结果
signed = util.p1SignMessage(signAlg, sourceData, priKey, session);
} catch (Exception e) {
throw new Exception("报文SM2签名失败");
}
String checkValue = new String(signed);
return String.format("%-256s", checkValue);
}
public static String getSignDataStr1(Map<String, String> map) {
List<String> keys = new ArrayList<String>(map.keySet());
Collections.sort(keys);
StringBuilder sb = new StringBuilder();
for(String key : keys){
if("sign".equals(key)) {
continue;
}
sb.append(key).append("=");
sb.append(map.get(key));
sb.append("&");
}
if(sb.length() > 0) {
sb.setLength(sb.length() - 1);
}
return sb.toString();
}
}

View File

@ -0,0 +1,264 @@
package com.yeledui.ysepay.utils;
import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.commons.httpclient.NameValuePair;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
import org.apache.commons.httpclient.params.HttpMethodParams;
import org.apache.commons.lang.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.util.EntityUtils;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.Map;
public class HttpRequestUtil {
/**
* <p>执行一个HTTP POST请求</p>
*
* @param url 请求的URL地址
* @param params 请求的查询参数,可以为null
* @param charset 字符集
* @param data xml格式的数据
* @return 返回请求响应的HTML
* @throws Exception
*/
public static String getDoPostResponse(String url,Map<String, String> params, String charset,String data,int timeout) throws Exception {
HttpClient client = new HttpClient();
HttpConnectionManagerParams httpManager = client.getHttpConnectionManager().getParams();
httpManager.setConnectionTimeout(timeout);
httpManager.setSoTimeout(timeout);
DefaultHttpMethodRetryHandler retryhandler = new DefaultHttpMethodRetryHandler(2,false);
client.getParams().setParameter(HttpMethodParams.RETRY_HANDLER, retryhandler);
client.getParams().setParameter(HttpMethodParams.HTTP_CONTENT_CHARSET, "UTF-8");
PostMethod method = new PostMethod(url);
StringBuffer sb = new StringBuffer();
if(data != null) {
RequestEntity entity = new StringRequestEntity(data,"application/x-www-form-urlencoded","UTF-8");
method.setRequestEntity(entity);
}
if (params != null) {
//设置Http Post参数
NameValuePair[] da = null;
da = new NameValuePair[params.size()];
int i = 0;
for (Map.Entry<String, String> entry : params.entrySet()) {
da[i] = new NameValuePair(entry.getKey(), entry.getValue());
i++;
}
i = 0;
System.out.println("data="+da.toString());
method.setRequestBody(da);
}
try {
client.executeMethod(method);
if(method.getStatusCode() == HttpStatus.SC_OK) {
BufferedReader reader = new BufferedReader(new InputStreamReader(method.getResponseBodyAsStream(),"UTF-8"));
String str = "";
while((str = reader.readLine())!=null){
sb.append(str);
}
}
} catch(Exception e) {
throw e;
} finally {
method.releaseConnection();
}
return sb.toString();
}
public static String httpPostWithjson(String reqUrl, String jsonStr) throws IOException {
String resp= null;
HttpURLConnection connection = null;
try {
URL url = new URL(reqUrl); //url地址
connection = (HttpURLConnection) url.openConnection();
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setRequestMethod("POST");
connection.setUseCaches(false);
connection.setInstanceFollowRedirects(true);
connection.setRequestProperty("Content-Type","application/json");
connection.connect();
try (OutputStream os = connection.getOutputStream()) {
os.write(jsonStr.getBytes("UTF-8"));
}
try (BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
String lines;
StringBuffer sbf = new StringBuffer();
while ((lines = reader.readLine()) != null) {
lines = new String(lines.getBytes(), "utf-8");
sbf.append(lines);
}
System.out.println("返回来的报文:"+sbf.toString());
resp = sbf.toString();
return resp;
}
} catch (Exception e) {
throw e;
}finally{
if(connection!=null){
connection.disconnect();
}
}
}
/**
* 图片上传接口未校验文件名称商户进件需要用到
* @param url
* @param paramMap
* @param file
* @return
* @throws Exception
*/
public static String sendPostFile(String url, Map<String,String> paramMap, File file) throws Exception {
HttpPost httpPost = new HttpPost(url);
//如果返回403 增加一下代码模拟浏览器
//httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0");;
CloseableHttpClient client = HttpClientBuilder.create().build();
MultipartEntityBuilder entity = MultipartEntityBuilder.create()
.setContentType(ContentType.MULTIPART_FORM_DATA)
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addBinaryBody("file", new FileInputStream(file), ContentType.DEFAULT_BINARY, file.getName()) //uploadFile对应服务端类的同名属性<File类型>
.setCharset(Charset.forName("utf-8"));
for (String key : paramMap.keySet()) {
String value = paramMap.get(key);
entity.addTextBody(key, value);
}
httpPost.setEntity(entity.build());
HttpResponse httpResponse = client.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
System.out.println(httpResponse.getStatusLine().getStatusCode());
}
HttpEntity resEntity = httpResponse.getEntity();
return null == resEntity ? "" : EntityUtils.toString(resEntity, "utf-8");
}
/**
* 文件上传 校验了文件名称支付宝实名认证文件上传用到
* @param url
* @param paramMap
* @param file
* @param fileName
* @return
* @throws Exception
*/
public static String sendPostFileAndName(String url, Map<String,String> paramMap, File file,String fileName) throws Exception {
if(StringUtils.isEmpty(fileName)){
throw new Exception("文件名称不能为空");
}
HttpPost httpPost = new HttpPost(url);
//如果返回403 增加一下代码模拟浏览器
//httpPost.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0");;
CloseableHttpClient client = HttpClientBuilder.create().build();
MultipartEntityBuilder entity = MultipartEntityBuilder.create()
.setContentType(ContentType.MULTIPART_FORM_DATA)
.setMode(HttpMultipartMode.BROWSER_COMPATIBLE)
.addBinaryBody("file", new FileInputStream(file), ContentType.DEFAULT_BINARY, fileName) //uploadFile对应服务端类的同名属性<File类型>
.setCharset(Charset.forName("utf-8"));
for (String key : paramMap.keySet()) {
String value = paramMap.get(key);
entity.addTextBody(key, value);
}
httpPost.setEntity(entity.build());
HttpResponse httpResponse = client.execute(httpPost);
if (httpResponse.getStatusLine().getStatusCode() != HttpStatus.SC_OK) {
System.out.println(httpResponse.getStatusLine().getStatusCode());
}
HttpEntity resEntity = httpResponse.getEntity();
return null == resEntity ? "" : EntityUtils.toString(resEntity, "utf-8");
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url
* 发送请求的 URL
* @param param
* 请求参数请求参数应该是 name1=value1&name2=value2 的形式
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param) {
PrintWriter out = null;
BufferedReader in = null;
String result = "";
try {
URL realUrl = new URL(url);
// 打开和URL之间的连接
HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection();
// 设置通用的请求属性
conn.setRequestMethod("POST");
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)");
conn.setRequestProperty("Accept-Charset", "UTF-8");
// 发送POST请求必须设置如下两行
conn.setDoOutput(true);
conn.setDoInput(true);
// 获取URLConnection对象对应的输出流
out = new PrintWriter(conn.getOutputStream());
// 发送请求参数
param = param.replaceAll("\\+", "%2B");
out.print(param);
// flush输出流的缓冲
out.flush();
// 定义BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
result += line;
}
} catch (Exception e) {
System.out.println("发送 POST 请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally块来关闭输出流输入流
finally {
try {
if (out != null) {
out.close();
}
if (in != null) {
in.close();
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
return result;
}
}

View File

@ -0,0 +1,72 @@
package com.yeledui.ysepay.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.fasterxml.jackson.databind.JsonNode;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang.StringUtils;
import java.util.*;
import static com.yeledui.ysepay.utils.Utils.*;
import static com.yeledui.ysepay.utils.Utils.getSerialNumber;
//公共方法
public class PublicCommon {
private static final String ALLCHAR = "0123456789ABCDEF";
/**
* 加签
* @param map
* @return
* @throws Exception
*/
public static String doSignature( Map<String,String> map) throws Exception {
List<String> keys = new ArrayList<String>(map.keySet());
Collections.sort(keys);
StringBuilder sb1 = new StringBuilder();
for(String k : keys){
if("sign".equals(k)) {
continue;
}
sb1.append(k).append("=");
sb1.append(map.get(k));
sb1.append("&");
}
if(sb1.length() > 0) {
sb1.setLength(sb1.length() - 1);
}
//私钥对排序的请求参数加签
String sign = GMSignUtils.signMsgSM2(getConfigProperties().getProperty("MERC_PRIVATE_FILE"),getConfigProperties().getProperty("MERC_PRIVATE_FILE_PASSWORD"), sb1.toString());
return sign;
}
/**
* 生成密钥key
* @return
*/
public static String secretKey(){
StringBuilder sb = new StringBuilder();
Random random = new Random();
for (int i = 0; i < 16; i++) {
sb.append(ALLCHAR.charAt(random.nextInt(ALLCHAR.length())));
}
return ByteUtil.toHexString(sb.toString());
}
/**
* 参数加密
* @param map
* @return
* @throws Exception
*/
public static String busEncrypt(Map<String,Object> map,String key) throws Exception {
JSONObject bizJSONObj = JSONObject.parseObject(JSON.toJSONString(map));
byte[] bte= AESUtil.encrypt(JSONObject.toJSONBytes(bizJSONObj, SerializerFeature.WriteNullStringAsEmpty), ByteUtil.hexStringToBytes(key));
return Base64.encodeBase64String(bte);
}
}

View File

@ -0,0 +1,89 @@
package com.yeledui.ysepay.utils;
/**
* 字符串格式化
*
* @author gientech
*/
public class StrFormatter
{
public static final String EMPTY_JSON = "{}";
public static final char C_BACKSLASH = '\\';
public static final char C_DELIM_START = '{';
public static final char C_DELIM_END = '}';
/**
* 格式化字符串<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param strPattern 字符串模板
* @param argArray 参数列表
* @return 结果
*/
public static String format(final String strPattern, final Object... argArray)
{
if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
{
return strPattern;
}
final int strPatternLength = strPattern.length();
// 初始化定义好的长度以获得更好的性能
StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
int handledPosition = 0;
int delimIndex;// 占位符所在位置
for (int argIndex = 0; argIndex < argArray.length; argIndex++)
{
delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
if (delimIndex == -1)
{
if (handledPosition == 0)
{
return strPattern;
}
else
{ // 字符串模板剩余部分不再包含占位符加入剩余部分后返回结果
sbuf.append(strPattern, handledPosition, strPatternLength);
return sbuf.toString();
}
}
else
{
if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
{
if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
{
// 转义符之前还有一个转义符占位符依旧有效
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
else
{
// 占位符被转义
argIndex--;
sbuf.append(strPattern, handledPosition, delimIndex - 1);
sbuf.append(C_DELIM_START);
handledPosition = delimIndex + 1;
}
}
else
{
// 正常占位符
sbuf.append(strPattern, handledPosition, delimIndex);
sbuf.append(Convert.utf8Str(argArray[argIndex]));
handledPosition = delimIndex + 2;
}
}
}
// 加入最后一个占位符后所有的字符
sbuf.append(strPattern, handledPosition, strPattern.length());
return sbuf.toString();
}
}

View File

@ -0,0 +1,619 @@
package com.yeledui.ysepay.utils;
import org.springframework.util.AntPathMatcher;
import java.util.*;
/**
* 字符串工具类
*
* @author gientech
*/
public class StringUtils extends org.apache.commons.lang3.StringUtils
{
/** 空字符串 */
private static final String NULLSTR = "";
/** 下划线 */
private static final char SEPARATOR = '_';
/**
* 获取参数不为空值
*
* @param value defaultValue 要判断的value
* @return value 返回值
*/
public static <T> T nvl(T value, T defaultValue)
{
return value != null ? value : defaultValue;
}
/**
* * 判断一个Collection是否为空 包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true为空 false非空
*/
public static boolean isEmpty(Collection<?> coll)
{
return isNull(coll) || coll.isEmpty();
}
/**
* * 判断一个Collection是否非空包含ListSetQueue
*
* @param coll 要判断的Collection
* @return true非空 false
*/
public static boolean isNotEmpty(Collection<?> coll)
{
return !isEmpty(coll);
}
/**
* * 判断一个对象数组是否为空
*
* @param objects 要判断的对象数组
** @return true为空 false非空
*/
public static boolean isEmpty(Object[] objects)
{
return isNull(objects) || (objects.length == 0);
}
/**
* * 判断一个对象数组是否非空
*
* @param objects 要判断的对象数组
* @return true非空 false
*/
public static boolean isNotEmpty(Object[] objects)
{
return !isEmpty(objects);
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true为空 false非空
*/
public static boolean isEmpty(Map<?, ?> map)
{
return isNull(map) || map.isEmpty();
}
/**
* * 判断一个Map是否为空
*
* @param map 要判断的Map
* @return true非空 false
*/
public static boolean isNotEmpty(Map<?, ?> map)
{
return !isEmpty(map);
}
/**
* * 判断一个字符串是否为空串
*
* @param str String
* @return true为空 false非空
*/
public static boolean isEmpty(String str)
{
return isNull(str) || NULLSTR.equals(str.trim());
}
/**
* * 判断一个字符串是否为非空串
*
* @param str String
* @return true非空串 false空串
*/
public static boolean isNotEmpty(String str)
{
return !isEmpty(str);
}
/**
* * 判断一个对象是否为空
*
* @param object Object
* @return true为空 false非空
*/
public static boolean isNull(Object object)
{
return object == null;
}
/**
* * 判断一个对象是否非空
*
* @param object Object
* @return true非空 false
*/
public static boolean isNotNull(Object object)
{
return !isNull(object);
}
/**
* * 判断一个对象是否是数组类型Java基本型别的数组
*
* @param object 对象
* @return true是数组 false不是数组
*/
public static boolean isArray(Object object)
{
return isNotNull(object) && object.getClass().isArray();
}
/**
* 去空格
*/
public static String trim(String str)
{
return (str == null ? "" : str.trim());
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @return 结果
*/
public static String substring(final String str, int start)
{
if (str == null)
{
return NULLSTR;
}
if (start < 0)
{
start = str.length() + start;
}
if (start < 0)
{
start = 0;
}
if (start > str.length())
{
return NULLSTR;
}
return str.substring(start);
}
/**
* 截取字符串
*
* @param str 字符串
* @param start 开始
* @param end 结束
* @return 结果
*/
public static String substring(final String str, int start, int end)
{
if (str == null)
{
return NULLSTR;
}
if (end < 0)
{
end = str.length() + end;
}
if (start < 0)
{
start = str.length() + start;
}
if (end > str.length())
{
end = str.length();
}
if (start > end)
{
return NULLSTR;
}
if (start < 0)
{
start = 0;
}
if (end < 0)
{
end = 0;
}
return str.substring(start, end);
}
/**
* 截取指定字符后的字符串
* @param substringAfter
* @param originalString
* @return
*/
public static String format(String substringAfter ,String originalString ){
int index = originalString.indexOf(substringAfter);
if (index != -1) {
String result = originalString.substring(index + substringAfter.length());
return result;
}
return null;
}
/**
* 格式化文本, {} 表示占位符<br>
* 此方法只是简单将占位符 {} 按照顺序替换为参数<br>
* 如果想输出 {} 使用 \\转义 { 即可如果想输出 {} 之前的 \ 使用双转义符 \\\\ 即可<br>
* <br>
* 通常使用format("this is {} for {}", "a", "b") -> this is a for b<br>
* 转义{} format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
* 转义\ format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
*
* @param template 文本模板被替换的部分用 {} 表示
* @param params 参数值
* @return 格式化后的文本
*/
public static String format(String template, Object... params)
{
if (isEmpty(params) || isEmpty(template))
{
return template;
}
return StrFormatter.format(template, params);
}
/**
* 是否为http(s)://开头
*
* @param link 链接
* @return 结果
*/
public static boolean ishttp(String link)
{
return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
}
/**
* 字符串转set
*
* @param str 字符串
* @param sep 分隔符
* @return set集合
*/
public static final Set<String> str2Set(String str, String sep)
{
return new HashSet<String>(str2List(str, sep, true, false));
}
/**
* 字符串转list
*
* @param str 字符串
* @param sep 分隔符
* @param filterBlank 过滤纯空白
* @param trim 去掉首尾空白
* @return list集合
*/
public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
{
List<String> list = new ArrayList<String>();
if (StringUtils.isEmpty(str))
{
return list;
}
// 过滤空白字符串
if (filterBlank && StringUtils.isBlank(str))
{
return list;
}
String[] split = str.split(sep);
for (String string : split)
{
if (filterBlank && StringUtils.isBlank(string))
{
continue;
}
if (trim)
{
string = string.trim();
}
list.add(string);
}
return list;
}
/**
* 查找指定字符串是否包含指定字符串列表中的任意一个字符串同时串忽略大小写
*
* @param cs 指定字符串
* @param searchCharSequences 需要检查的字符串数组
* @return 是否包含任意一个字符串
*/
public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
{
if (isEmpty(cs) || isEmpty(searchCharSequences))
{
return false;
}
for (CharSequence testStr : searchCharSequences)
{
if (containsIgnoreCase(cs, testStr))
{
return true;
}
}
return false;
}
/**
* 驼峰转下划线命名
*/
public static String toUnderScoreCase(String str)
{
if (str == null)
{
return null;
}
StringBuilder sb = new StringBuilder();
// 前置字符是否大写
boolean preCharIsUpperCase = true;
// 当前字符是否大写
boolean curreCharIsUpperCase = true;
// 下一字符是否大写
boolean nexteCharIsUpperCase = true;
for (int i = 0; i < str.length(); i++)
{
char c = str.charAt(i);
if (i > 0)
{
preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
}
else
{
preCharIsUpperCase = false;
}
curreCharIsUpperCase = Character.isUpperCase(c);
if (i < (str.length() - 1))
{
nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
}
if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
{
sb.append(SEPARATOR);
}
else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
{
sb.append(SEPARATOR);
}
sb.append(Character.toLowerCase(c));
}
return sb.toString();
}
/**
* 是否包含字符串
*
* @param str 验证字符串
* @param strs 字符串组
* @return 包含返回true
*/
public static boolean inStringIgnoreCase(String str, String... strs)
{
if (str != null && strs != null)
{
for (String s : strs)
{
if (str.equalsIgnoreCase(trim(s)))
{
return true;
}
}
}
return false;
}
/**
* 将下划线大写方式命名的字符串转换为驼峰式如果转换前的下划线大写方式命名的字符串为空则返回空字符串 例如HELLO_WORLD->HelloWorld
*
* @param name 转换前的下划线大写方式命名的字符串
* @return 转换后的驼峰式命名的字符串
*/
public static String convertToCamelCase(String name)
{
StringBuilder result = new StringBuilder();
// 快速检查
if (name == null || name.isEmpty())
{
// 没必要转换
return "";
}
else if (!name.contains("_"))
{
// 不含下划线仅将首字母大写
return name.substring(0, 1).toUpperCase() + name.substring(1);
}
// 用下划线将原始字符串分割
String[] camels = name.split("_");
for (String camel : camels)
{
// 跳过原始字符串中开头结尾的下换线或双重下划线
if (camel.isEmpty())
{
continue;
}
// 首字母大写
result.append(camel.substring(0, 1).toUpperCase());
result.append(camel.substring(1).toLowerCase());
}
return result.toString();
}
/**
* 驼峰式命名法 例如user_name->userName
*/
public static String toCamelCase(String s)
{
if (s == null)
{
return null;
}
s = s.toLowerCase();
StringBuilder sb = new StringBuilder(s.length());
boolean upperCase = false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if (c == SEPARATOR)
{
upperCase = true;
}
else if (upperCase)
{
sb.append(Character.toUpperCase(c));
upperCase = false;
}
else
{
sb.append(c);
}
}
return sb.toString();
}
/**
* 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
*
* @param str 指定字符串
* @param strs 需要检查的字符串数组
* @return 是否匹配
*/
public static boolean matches(String str, List<String> strs)
{
if (isEmpty(str) || isEmpty(strs))
{
return false;
}
for (String pattern : strs)
{
if (isMatch(pattern, str))
{
return true;
}
}
return false;
}
/**
* 判断url是否与规则配置:
* ? 表示单个字符;
* * 表示一层路径内的任意字符串不可跨层级;
* ** 表示任意层路径;
*
* @param pattern 匹配规则
* @param url 需要匹配的url
* @return
*/
public static boolean isMatch(String pattern, String url)
{
AntPathMatcher matcher = new AntPathMatcher();
return matcher.match(pattern, url);
}
@SuppressWarnings("unchecked")
public static <T> T cast(Object obj)
{
return (T) obj;
}
/**
* 数字左边补齐0使之达到指定长度注意如果数字转换为字符串后长度大于size则只保留 最后size个字符
*
* @param num 数字对象
* @param size 字符串指定长度
* @return 返回数字的字符串格式该字符串为指定长度
*/
public static final String padl(final Number num, final int size)
{
return padl(num.toString(), size, '0');
}
/**
* 字符串左补齐如果原始字符串s长度大于size则只保留最后size个字符
*
* @param s 原始字符串
* @param size 字符串指定长度
* @param c 用于补齐的字符
* @return 返回指定长度的字符串由原字符串左补齐或截取得到
*/
public static final String padl(final String s, final int size, final char c)
{
final StringBuilder sb = new StringBuilder(size);
if (s != null)
{
final int len = s.length();
if (s.length() <= size)
{
for (int i = size - len; i > 0; i--)
{
sb.append(c);
}
sb.append(s);
}
else
{
return s.substring(len - size, len);
}
}
else
{
for (int i = size; i > 0; i--)
{
sb.append(c);
}
}
return sb.toString();
}
public static String subStartBetweenEndString(final String str,String startStr,String endStr){
int startIndex = str.indexOf(startStr);
int endIndex = str.indexOf(endStr,startIndex + 1);
// 如果字符未找到则返回原始字符串
if (startIndex == -1 || endIndex == -1) {
return str;
}
// 删除指定字符之间的字符
String result = str.substring(0, startIndex)
+ str.substring(endIndex + 1, str.length());
return result;
}
public static boolean containsString(String[] array, String target) {
for (String element : array) {
if (element.equals(target)) {
return true;
}
}
return false;
}
public static void main(String[] args) {
System.out.println(StringUtils.format("baidu_sdk","/www/wwwroot/bin/go/baidu_sdk/static/img/20240731/1722409200292_微信图片_20240612150538.jpg"));
}
}

View File

@ -0,0 +1,67 @@
package com.yeledui.ysepay.utils;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @类名称TextFileHelper
* @类描述读取文件
* @作者zhanggy
* @日期2021年8月11日
*/
public final class TextFileHelper {
private TextFileHelper() {
}
/**
* 读文件
* @param file 文件路径
* @return 文件内容
* @throws IOException
*/
public static final byte[] readFile(String file) throws IOException {
int offset = 0;
FileInputStream in = null;
try {
in = new FileInputStream(file);
byte[] out = new byte[in.available()];
if (out.length < offset + in.available()) {
throw new IOException("Illegal Argument: filepath");
}
byte[] buffer = new byte[1024];
int numRead;
while ((numRead = in.read(buffer, 0, buffer.length)) >= 0) {
System.arraycopy(buffer, 0, out, offset, numRead);
offset += numRead;
}
return out;
} finally {
if(in != null){
in.close();
}
}
}
/**
* 写文件
* @param filePath
* @param data
* @throws IOException
*/
public static final void writeFile(String filePath, byte[] data) throws IOException {
FileOutputStream out = null;
try {
out = new FileOutputStream(filePath);
out.write(data, 0, data.length);
}finally{
if(out != null){
out.close();
}
}
}
}

View File

@ -0,0 +1,174 @@
package com.yeledui.ysepay.utils;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang.StringUtils;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
public class Utils {
/**
* 读取json文件
* @param AFilename json文件名称
* @return
*/
public static JsonNode LoadJsonFromFile(String AFilename) {
try {
ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree(new File(AFilename));
return json;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
public static JSONObject readJsonFile(String jsonPath) throws IOException {
ObjectMapper mapper = new ObjectMapper();
Map<String, Object> map = mapper.readValue(new File(jsonPath), Map.class);
JSONObject obj = new JSONObject(map);
return obj;
}
/**
* 获取当前时间
* @param pattern 格式
* @return
*/
public static String getCurrentDateTime(String pattern){
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
return sdf.format(new Date());
}
public static String toFormatDate(String dateStr,String format,String toFormat) throws ParseException {
SimpleDateFormat inputFormat = new SimpleDateFormat(format);
Date parsedDate = inputFormat.parse(dateStr);
SimpleDateFormat outputFormat = new SimpleDateFormat(toFormat);
return outputFormat.format(parsedDate);
}
/**
* 流水号
* @return
*/
public static synchronized String getSerialNumber() {
// 时间格式化
SimpleDateFormat sdf = new SimpleDateFormat("yyMMddHHmmss");
String dateStr = sdf.format(new Date());
// 获取随机两位字母
Random random = new Random();
String letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
//随机生成六位数字并拼接成字符串
String digitString = "";
for (int i = 0; i < 6; i++) {
digitString = digitString + random.nextInt(10);
}
String serialNumber = letters.charAt(random.nextInt(52))+"" + letters.charAt(random.nextInt(52))+"" +digitString + dateStr;
return serialNumber;
}
public static Properties getConfigProperties() {
Properties properties = new Properties();
//String proPath = "E:\\gyx\\Projects For Java\\yspay_api_java\\uploadInfo\\src\\main\\resources\\config.properties";
//String proPath = "/home/user/projects/yspay_api_java/pay/config.properties";
String proPath = "D:\\duancheng_java\\ysepay\\src\\main\\resources\\application.properties";
try {
FileInputStream fileInputStream = new FileInputStream(proPath);
properties.load(fileInputStream);
fileInputStream.close();
} catch (IOException e) {
System.out.println("配置文件读取失败"+e.toString());
e.printStackTrace();
}
return properties;
}
/**
* map 转成 string
* @param map
* @return
*/
public static String mapToString(Map<String, String> map) {
SortedMap<String, String> sortedMap = new TreeMap<String, String>(map);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> entry : sortedMap.entrySet()) {
if (StringUtils.isBlank(entry.getValue())) {
continue;
}
sb.append(entry.getKey()).append('=').append(entry.getValue()).append('&');
}
sb.deleteCharAt(sb.length() - 1);
return sb.length() == 0 ? "" : sb.toString();
}
/**
* 把数组所有元素排序并按照参数=参数值的模式用&字符拼接成字符串
*
* @param params
* 需要排序并参与字符拼接的参数组
* @return 拼接后字符串
*/
public static String createLinkString(Map<String, String> params) {
List<String> keys = new ArrayList<String>(params.keySet());
Collections.sort(keys);
String prestr = "";
for (int i = 0; i < keys.size(); i++) {
String key = keys.get(i);
String value = params.get(key);
if (i == keys.size() - 1) {
prestr = prestr + key + "=" + value;
} else {
prestr = prestr + key + "=" + value + "&";
}
}
return prestr;
}
/**
* 除去数组中的空值和签名参数
*
* @param sArray
* 签名参数组
* @return 去掉空值与签名参数后的新签名参数组
*/
public static Map<String, String> paraFilter(Map<String, String> sArray) {
Map<String, String> result = new HashMap<String, String>();
if (sArray == null || sArray.size() <= 0) {
return result;
}
for (String key : sArray.keySet()) {
String value = sArray.get(key);
if (value == null || StringUtils.isEmpty(value) || key.equalsIgnoreCase("sign")) {
continue;
}
result.put(key, value);
}
return result;
}
}

View File

@ -0,0 +1,69 @@
package com.yeledui.ysepay.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.parser.Feature;
import org.apache.commons.codec.binary.Base64;
import java.util.Map;
import static com.yeledui.ysepay.utils.Utils.getConfigProperties;
public class YsPaySignUtils {
/**
* 同步请求参数签名
*/
public static String sign(Map<String, String> mapData) throws Exception {
String signContent = Utils.mapToString(mapData);
String sign=GMSignUtils.signMsgSM2(getConfigProperties().getProperty("MERC_PRIVATE_FILE"),getConfigProperties().getProperty("MERC_PRIVATE_FILE_PASSWORD"),signContent);
return sign;
}
/**
* 同步返回参数验签
*
* @throws Exception
*/
public static boolean resultVerify(String resTest, String repMethod) throws Exception {
JSONObject jsonObject= JSON.parseObject(resTest, Feature.OrderedField);
String content = jsonObject.get(repMethod).toString();
String sign = jsonObject.get("sign").toString();
String path = getConfigProperties().getProperty("YS_PUBLIC_CER_PATH");
GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(path);
byte[] srcData = content.getBytes("UTF-8");
boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo,Base64.decodeBase64(sign.getBytes("UTF-8")),srcData);
return validateSignResult;
}
/**
* 异步通知参数验签
*/
public static boolean asynVerifyYs(Map<String, String> reqMap) throws Exception {
//请用银盛的公钥证书
//公钥地址
String path = "/sm2/sm2businessgate.cer";
//获取银盛公钥
GMCertInfo verifyCertInfo = GMSignUtils.getVerifyCertInfo(path);
//验签
String sign = reqMap.get("sign");
System.out.println("签名原文:"+reqMap);
String content = Utils.createLinkString(Utils.paraFilter(reqMap));
System.out.println("验签数据"+content+","+sign);
byte[] srcData = content.getBytes("UTF-8");
boolean validateSignResult = GMSignUtils.verifyMsgSignSM2(verifyCertInfo,Base64.decodeBase64(sign.getBytes("UTF-8")),srcData);
return validateSignResult;
}
public static String encryptData(String data) throws Exception{
//请用银盛的公钥证书
//公钥地址
String path = "/sm2/sm2businessgate.cer";
// String path = "C:\\Users\\Lenovo\\Desktop\\Sm2\\sm2businessgate\\sm2businessgate.cer";
//加密
return GMSignUtils.encryptData(path,data);
}
}

View File

@ -0,0 +1,30 @@
spring.application.name=ysepay
# ??????
# ??
#HTTP_NET = https://appdev.ysepay.com/openapi
# ??
HTTP_NET = https://ysgate.ysepay.com/openapi
#??
#CERT_ID: 826341457228011
#??
CERT_ID = 826452972730006
# ?????????
#??
#YS_PUBLIC_CER_PATH = D:/datas/SM2-test/sm2businessgate.cer
#??
YS_PUBLIC_CER_PATH = D:/datas/SM2-Pro/sm2businessgate.cer
# ???????
# ??
#MERC_PRIVATE_FILE = D:/datas/SM2-test/826341457228011.sm2
#??
MERC_PRIVATE_FILE = D:/datas/SM2-Pro/826452972730006.sm2
# ?????????
#??
#MERC_PRIVATE_FILE_PASSWORD = a1234567
#??
MERC_PRIVATE_FILE_PASSWORD = angya123456

View File

@ -0,0 +1,13 @@
package com.yeledui.ysepay;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest
class YsepayApplicationTests {
@Test
void contextLoads() {
}
}