mirror of
https://gitee.com/egzosn/pay-java-parent.git
synced 2026-09-23 17:08:58 +08:00
#新增#
新增退款接口 新增接口等注释 #修改# 更新新的支付接口
This commit is contained in:
@@ -0,0 +1,310 @@
|
||||
package com.egzosn.pay.common.util.sign.SM3;
|
||||
|
||||
public class SM3
|
||||
{
|
||||
public static final byte[] iv = { 0x73, (byte) 0x80, 0x16, 0x6f, 0x49,
|
||||
0x14, (byte) 0xb2, (byte) 0xb9, 0x17, 0x24, 0x42, (byte) 0xd7,
|
||||
(byte) 0xda, (byte) 0x8a, 0x06, 0x00, (byte) 0xa9, 0x6f, 0x30,
|
||||
(byte) 0xbc, (byte) 0x16, 0x31, 0x38, (byte) 0xaa, (byte) 0xe3,
|
||||
(byte) 0x8d, (byte) 0xee, 0x4d, (byte) 0xb0, (byte) 0xfb, 0x0e,
|
||||
0x4e };
|
||||
|
||||
public static int[] Tj = new int[64];
|
||||
|
||||
static
|
||||
{
|
||||
for (int i = 0; i < 16; i++)
|
||||
{
|
||||
Tj[i] = 0x79cc4519;
|
||||
}
|
||||
|
||||
for (int i = 16; i < 64; i++)
|
||||
{
|
||||
Tj[i] = 0x7a879d8a;
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] CF(byte[] V, byte[] B)
|
||||
{
|
||||
int[] v, b;
|
||||
v = convert(V);
|
||||
b = convert(B);
|
||||
return convert(CF(v, b));
|
||||
}
|
||||
|
||||
private static int[] convert(byte[] arr)
|
||||
{
|
||||
int[] out = new int[arr.length / 4];
|
||||
byte[] tmp = new byte[4];
|
||||
for (int i = 0; i < arr.length; i += 4)
|
||||
{
|
||||
System.arraycopy(arr, i, tmp, 0, 4);
|
||||
out[i / 4] = bigEndianByteToInt(tmp);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
private static byte[] convert(int[] arr)
|
||||
{
|
||||
byte[] out = new byte[arr.length * 4];
|
||||
byte[] tmp = null;
|
||||
for (int i = 0; i < arr.length; i++)
|
||||
{
|
||||
tmp = bigEndianIntToByte(arr[i]);
|
||||
System.arraycopy(tmp, 0, out, i * 4, 4);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static int[] CF(int[] V, int[] B)
|
||||
{
|
||||
int a, b, c, d, e, f, g, h;
|
||||
int ss1, ss2, tt1, tt2;
|
||||
a = V[0];
|
||||
b = V[1];
|
||||
c = V[2];
|
||||
d = V[3];
|
||||
e = V[4];
|
||||
f = V[5];
|
||||
g = V[6];
|
||||
h = V[7];
|
||||
|
||||
int[][] arr = expand(B);
|
||||
int[] w = arr[0];
|
||||
int[] w1 = arr[1];
|
||||
|
||||
for (int j = 0; j < 64; j++)
|
||||
{
|
||||
ss1 = (bitCycleLeft(a, 12) + e + bitCycleLeft(Tj[j], j));
|
||||
ss1 = bitCycleLeft(ss1, 7);
|
||||
ss2 = ss1 ^ bitCycleLeft(a, 12);
|
||||
tt1 = FFj(a, b, c, j) + d + ss2 + w1[j];
|
||||
tt2 = GGj(e, f, g, j) + h + ss1 + w[j];
|
||||
d = c;
|
||||
c = bitCycleLeft(b, 9);
|
||||
b = a;
|
||||
a = tt1;
|
||||
h = g;
|
||||
g = bitCycleLeft(f, 19);
|
||||
f = e;
|
||||
e = P0(tt2);
|
||||
|
||||
/*System.out.print(j+" ");
|
||||
System.out.print(Integer.toHexString(a)+" ");
|
||||
System.out.print(Integer.toHexString(b)+" ");
|
||||
System.out.print(Integer.toHexString(c)+" ");
|
||||
System.out.print(Integer.toHexString(d)+" ");
|
||||
System.out.print(Integer.toHexString(e)+" ");
|
||||
System.out.print(Integer.toHexString(f)+" ");
|
||||
System.out.print(Integer.toHexString(g)+" ");
|
||||
System.out.print(Integer.toHexString(h)+" ");
|
||||
System.out.println("");*/
|
||||
}
|
||||
// System.out.println("");
|
||||
|
||||
int[] out = new int[8];
|
||||
out[0] = a ^ V[0];
|
||||
out[1] = b ^ V[1];
|
||||
out[2] = c ^ V[2];
|
||||
out[3] = d ^ V[3];
|
||||
out[4] = e ^ V[4];
|
||||
out[5] = f ^ V[5];
|
||||
out[6] = g ^ V[6];
|
||||
out[7] = h ^ V[7];
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
private static int[][] expand(int[] B)
|
||||
{
|
||||
int W[] = new int[68];
|
||||
int W1[] = new int[64];
|
||||
for (int i = 0; i < B.length; i++)
|
||||
{
|
||||
W[i] = B[i];
|
||||
}
|
||||
|
||||
for (int i = 16; i < 68; i++)
|
||||
{
|
||||
W[i] = P1(W[i - 16] ^ W[i - 9] ^ bitCycleLeft(W[i - 3], 15))
|
||||
^ bitCycleLeft(W[i - 13], 7) ^ W[i - 6];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
W1[i] = W[i] ^ W[i + 4];
|
||||
}
|
||||
|
||||
int arr[][] = new int[][] { W, W1 };
|
||||
return arr;
|
||||
}
|
||||
|
||||
private static byte[] bigEndianIntToByte(int num)
|
||||
{
|
||||
return back(Util.intToBytes(num));
|
||||
}
|
||||
|
||||
private static int bigEndianByteToInt(byte[] bytes)
|
||||
{
|
||||
return Util.byteToInt(back(bytes));
|
||||
}
|
||||
|
||||
private static int FFj(int X, int Y, int Z, int j)
|
||||
{
|
||||
if (j >= 0 && j <= 15)
|
||||
{
|
||||
return FF1j(X, Y, Z);
|
||||
}
|
||||
else
|
||||
{
|
||||
return FF2j(X, Y, Z);
|
||||
}
|
||||
}
|
||||
|
||||
private static int GGj(int X, int Y, int Z, int j)
|
||||
{
|
||||
if (j >= 0 && j <= 15)
|
||||
{
|
||||
return GG1j(X, Y, Z);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GG2j(X, Y, Z);
|
||||
}
|
||||
}
|
||||
|
||||
// 逻辑位运算函数
|
||||
private static int FF1j(int X, int Y, int Z)
|
||||
{
|
||||
int tmp = X ^ Y ^ Z;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static int FF2j(int X, int Y, int Z)
|
||||
{
|
||||
int tmp = ((X & Y) | (X & Z) | (Y & Z));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static int GG1j(int X, int Y, int Z)
|
||||
{
|
||||
int tmp = X ^ Y ^ Z;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static int GG2j(int X, int Y, int Z)
|
||||
{
|
||||
int tmp = (X & Y) | (~X & Z);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static int P0(int X)
|
||||
{
|
||||
int y = rotateLeft(X, 9);
|
||||
y = bitCycleLeft(X, 9);
|
||||
int z = rotateLeft(X, 17);
|
||||
z = bitCycleLeft(X, 17);
|
||||
int t = X ^ y ^ z;
|
||||
return t;
|
||||
}
|
||||
|
||||
private static int P1(int X)
|
||||
{
|
||||
int t = X ^ bitCycleLeft(X, 15) ^ bitCycleLeft(X, 23);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对最后一个分组字节数据padding
|
||||
*
|
||||
* @param in
|
||||
* @param bLen
|
||||
* 分组个数
|
||||
* @return
|
||||
*/
|
||||
public static byte[] padding(byte[] in, int bLen)
|
||||
{
|
||||
int k = 448 - (8 * in.length + 1) % 512;
|
||||
if (k < 0)
|
||||
{
|
||||
k = 960 - (8 * in.length + 1) % 512;
|
||||
}
|
||||
k += 1;
|
||||
byte[] padd = new byte[k / 8];
|
||||
padd[0] = (byte) 0x80;
|
||||
long n = in.length * 8 + bLen * 512;
|
||||
byte[] out = new byte[in.length + k / 8 + 64 / 8];
|
||||
int pos = 0;
|
||||
System.arraycopy(in, 0, out, 0, in.length);
|
||||
pos += in.length;
|
||||
System.arraycopy(padd, 0, out, pos, padd.length);
|
||||
pos += padd.length;
|
||||
byte[] tmp = back(Util.longToBytes(n));
|
||||
System.arraycopy(tmp, 0, out, pos, tmp.length);
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字节数组逆序
|
||||
*
|
||||
* @param in
|
||||
* @return
|
||||
*/
|
||||
private static byte[] back(byte[] in)
|
||||
{
|
||||
byte[] out = new byte[in.length];
|
||||
for (int i = 0; i < out.length; i++)
|
||||
{
|
||||
out[i] = in[out.length - i - 1];
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public static int rotateLeft(int x, int n)
|
||||
{
|
||||
return (x << n) | (x >> (32 - n));
|
||||
}
|
||||
|
||||
private static int bitCycleLeft(int n, int bitLen)
|
||||
{
|
||||
bitLen %= 32;
|
||||
byte[] tmp = bigEndianIntToByte(n);
|
||||
int byteLen = bitLen / 8;
|
||||
int len = bitLen % 8;
|
||||
if (byteLen > 0)
|
||||
{
|
||||
tmp = byteCycleLeft(tmp, byteLen);
|
||||
}
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
tmp = bitSmall8CycleLeft(tmp, len);
|
||||
}
|
||||
|
||||
return bigEndianByteToInt(tmp);
|
||||
}
|
||||
|
||||
private static byte[] bitSmall8CycleLeft(byte[] in, int len)
|
||||
{
|
||||
byte[] tmp = new byte[in.length];
|
||||
int t1, t2, t3;
|
||||
for (int i = 0; i < tmp.length; i++)
|
||||
{
|
||||
t1 = (byte) ((in[i] & 0x000000ff) << len);
|
||||
t2 = (byte) ((in[(i + 1) % tmp.length] & 0x000000ff) >> (8 - len));
|
||||
t3 = (byte) (t1 | t2);
|
||||
tmp[i] = (byte) t3;
|
||||
}
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
private static byte[] byteCycleLeft(byte[] in, int byteLen)
|
||||
{
|
||||
byte[] tmp = new byte[in.length];
|
||||
System.arraycopy(in, byteLen, tmp, 0, in.length - byteLen);
|
||||
System.arraycopy(in, 0, tmp, in.length - byteLen, byteLen);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
package com.egzosn.pay.common.util.sign.SM3;
|
||||
|
||||
public class SM3Digest
|
||||
{
|
||||
/** SM3值的长度 */
|
||||
private static final int BYTE_LENGTH = 32;
|
||||
|
||||
/** SM3分组长度 */
|
||||
private static final int BLOCK_LENGTH = 64;
|
||||
|
||||
/** 缓冲区长度 */
|
||||
private static final int BUFFER_LENGTH = BLOCK_LENGTH * 1;
|
||||
|
||||
/** 缓冲区 */
|
||||
private byte[] xBuf = new byte[BUFFER_LENGTH];
|
||||
|
||||
/** 缓冲区偏移量 */
|
||||
private int xBufOff;
|
||||
|
||||
/** 初始向量 */
|
||||
private byte[] V = SM3.iv.clone();
|
||||
|
||||
private int cntBlock = 0;
|
||||
|
||||
public SM3Digest() {
|
||||
}
|
||||
|
||||
public SM3Digest(SM3Digest t)
|
||||
{
|
||||
System.arraycopy(t.xBuf, 0, this.xBuf, 0, t.xBuf.length);
|
||||
this.xBufOff = t.xBufOff;
|
||||
System.arraycopy(t.V, 0, this.V, 0, t.V.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* SM3结果输出
|
||||
*
|
||||
* @param out 保存SM3结构的缓冲区
|
||||
* @param outOff 缓冲区偏移量
|
||||
* @return
|
||||
*/
|
||||
public int doFinal(byte[] out, int outOff)
|
||||
{
|
||||
byte[] tmp = doFinal();
|
||||
System.arraycopy(tmp, 0, out, 0, tmp.length);
|
||||
return BYTE_LENGTH;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
xBufOff = 0;
|
||||
cntBlock = 0;
|
||||
V = SM3.iv.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* 明文输入
|
||||
*
|
||||
* @param in
|
||||
* 明文输入缓冲区
|
||||
* @param inOff
|
||||
* 缓冲区偏移量
|
||||
* @param len
|
||||
* 明文长度
|
||||
*/
|
||||
public void update(byte[] in, int inOff, int len)
|
||||
{
|
||||
int partLen = BUFFER_LENGTH - xBufOff;
|
||||
int inputLen = len;
|
||||
int dPos = inOff;
|
||||
if (partLen < inputLen)
|
||||
{
|
||||
System.arraycopy(in, dPos, xBuf, xBufOff, partLen);
|
||||
inputLen -= partLen;
|
||||
dPos += partLen;
|
||||
doUpdate();
|
||||
while (inputLen > BUFFER_LENGTH)
|
||||
{
|
||||
System.arraycopy(in, dPos, xBuf, 0, BUFFER_LENGTH);
|
||||
inputLen -= BUFFER_LENGTH;
|
||||
dPos += BUFFER_LENGTH;
|
||||
doUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
System.arraycopy(in, dPos, xBuf, xBufOff, inputLen);
|
||||
xBufOff += inputLen;
|
||||
}
|
||||
|
||||
private void doUpdate()
|
||||
{
|
||||
byte[] B = new byte[BLOCK_LENGTH];
|
||||
for (int i = 0; i < BUFFER_LENGTH; i += BLOCK_LENGTH)
|
||||
{
|
||||
System.arraycopy(xBuf, i, B, 0, B.length);
|
||||
doHash(B);
|
||||
}
|
||||
xBufOff = 0;
|
||||
}
|
||||
|
||||
private void doHash(byte[] B)
|
||||
{
|
||||
byte[] tmp = SM3.CF(V, B);
|
||||
System.arraycopy(tmp, 0, V, 0, V.length);
|
||||
cntBlock++;
|
||||
}
|
||||
|
||||
private byte[] doFinal()
|
||||
{
|
||||
byte[] B = new byte[BLOCK_LENGTH];
|
||||
byte[] buffer = new byte[xBufOff];
|
||||
System.arraycopy(xBuf, 0, buffer, 0, buffer.length);
|
||||
byte[] tmp = SM3.padding(buffer, cntBlock);
|
||||
for (int i = 0; i < tmp.length; i += BLOCK_LENGTH)
|
||||
{
|
||||
System.arraycopy(tmp, i, B, 0, B.length);
|
||||
doHash(B);
|
||||
}
|
||||
return V;
|
||||
}
|
||||
|
||||
public void update(byte in)
|
||||
{
|
||||
byte[] buffer = new byte[] { in };
|
||||
update(buffer, 0, 1);
|
||||
}
|
||||
|
||||
public int getDigestSize()
|
||||
{
|
||||
return BYTE_LENGTH;
|
||||
}
|
||||
//
|
||||
// public static void main(String[] args)
|
||||
// {
|
||||
// byte[] md = new byte[32];
|
||||
// byte[] msg1 = "ererfeiisgod".getBytes();
|
||||
// SM3Digest sm3 = new SM3Digest();
|
||||
// sm3.update(msg1, 0, msg1.length);
|
||||
// sm3.doFinal(md, 0);
|
||||
// String s = new String(Hex.encode(md));
|
||||
// System.out.println(s.toUpperCase());
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,662 @@
|
||||
package com.egzosn.pay.common.util.sign.SM3;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class Util
|
||||
{
|
||||
/**
|
||||
* 整形转换成网络传输的字节流(字节数组)型数据
|
||||
*
|
||||
* @param num 一个整型数据
|
||||
* @return 4个字节的自己数组
|
||||
*/
|
||||
public static byte[] intToBytes(int num)
|
||||
{
|
||||
byte[] bytes = new byte[4];
|
||||
bytes[0] = (byte) (0xff & (num >> 0));
|
||||
bytes[1] = (byte) (0xff & (num >> 8));
|
||||
bytes[2] = (byte) (0xff & (num >> 16));
|
||||
bytes[3] = (byte) (0xff & (num >> 24));
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 四个字节的字节数据转换成一个整形数据
|
||||
*
|
||||
* @param bytes 4个字节的字节数组
|
||||
* @return 一个整型数据
|
||||
*/
|
||||
public static int byteToInt(byte[] bytes)
|
||||
{
|
||||
int num = 0;
|
||||
int temp;
|
||||
temp = (0x000000ff & (bytes[0])) << 0;
|
||||
num = num | temp;
|
||||
temp = (0x000000ff & (bytes[1])) << 8;
|
||||
num = num | temp;
|
||||
temp = (0x000000ff & (bytes[2])) << 16;
|
||||
num = num | temp;
|
||||
temp = (0x000000ff & (bytes[3])) << 24;
|
||||
num = num | temp;
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
* 长整形转换成网络传输的字节流(字节数组)型数据
|
||||
*
|
||||
* @param num 一个长整型数据
|
||||
* @return 4个字节的自己数组
|
||||
*/
|
||||
public static byte[] longToBytes(long num)
|
||||
{
|
||||
byte[] bytes = new byte[8];
|
||||
for (int i = 0; i < 8; i++)
|
||||
{
|
||||
bytes[i] = (byte) (0xff & (num >> (i * 8)));
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* 大数字转换字节流(字节数组)型数据
|
||||
*
|
||||
* @param n
|
||||
* @return
|
||||
*/
|
||||
public static byte[] byteConvert32Bytes(BigInteger n)
|
||||
{
|
||||
byte tmpd[] = (byte[])null;
|
||||
if(n == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if(n.toByteArray().length == 33)
|
||||
{
|
||||
tmpd = new byte[32];
|
||||
System.arraycopy(n.toByteArray(), 1, tmpd, 0, 32);
|
||||
}
|
||||
else if(n.toByteArray().length == 32)
|
||||
{
|
||||
tmpd = n.toByteArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpd = new byte[32];
|
||||
for(int i = 0; i < 32 - n.toByteArray().length; i++)
|
||||
{
|
||||
tmpd[i] = 0;
|
||||
}
|
||||
System.arraycopy(n.toByteArray(), 0, tmpd, 32 - n.toByteArray().length, n.toByteArray().length);
|
||||
}
|
||||
return tmpd;
|
||||
}
|
||||
|
||||
/**
|
||||
* 换字节流(字节数组)型数据转大数字
|
||||
*
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
public static BigInteger byteConvertInteger(byte[] b)
|
||||
{
|
||||
if (b[0] < 0)
|
||||
{
|
||||
byte[] temp = new byte[b.length + 1];
|
||||
temp[0] = 0;
|
||||
System.arraycopy(b, 0, temp, 1, b.length);
|
||||
return new BigInteger(temp);
|
||||
}
|
||||
return new BigInteger(b);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字节数组获得值(十六进制数字)
|
||||
*
|
||||
* @param bytes
|
||||
* @return
|
||||
*/
|
||||
public static String getHexString(byte[] bytes)
|
||||
{
|
||||
return getHexString(bytes, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据字节数组获得值(十六进制数字)
|
||||
*
|
||||
* @param bytes
|
||||
* @param upperCase
|
||||
* @return
|
||||
*/
|
||||
public static String getHexString(byte[] bytes, boolean upperCase)
|
||||
{
|
||||
String ret = "";
|
||||
for (int i = 0; i < bytes.length; i++)
|
||||
{
|
||||
ret += Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1);
|
||||
}
|
||||
return upperCase ? ret.toUpperCase() : ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印十六进制字符串
|
||||
*
|
||||
* @param bytes
|
||||
*/
|
||||
public static void printHexString(byte[] bytes)
|
||||
{
|
||||
for (int i = 0; i < bytes.length; i++)
|
||||
{
|
||||
String hex = Integer.toHexString(bytes[i] & 0xFF);
|
||||
if (hex.length() == 1)
|
||||
{
|
||||
hex = '0' + hex;
|
||||
}
|
||||
System.out.print("0x" + hex.toUpperCase() + ",");
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert hex string to byte[]
|
||||
*
|
||||
* @param hexString
|
||||
* the hex string
|
||||
* @return byte[]
|
||||
*/
|
||||
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]));
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert char to byte
|
||||
*
|
||||
* @param c
|
||||
* char
|
||||
* @return byte
|
||||
*/
|
||||
public static byte charToByte(char c)
|
||||
{
|
||||
return (byte) "0123456789ABCDEF".indexOf(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用于建立十六进制字符的输出的小写字符数组
|
||||
*/
|
||||
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
|
||||
|
||||
/**
|
||||
* 用于建立十六进制字符的输出的大写字符数组
|
||||
*/
|
||||
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5',
|
||||
'6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符数组
|
||||
*
|
||||
* @param data byte[]
|
||||
* @return 十六进制char[]
|
||||
*/
|
||||
public static char[] encodeHex(byte[] data) {
|
||||
return encodeHex(data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符数组
|
||||
*
|
||||
* @param data byte[]
|
||||
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
|
||||
* @return 十六进制char[]
|
||||
*/
|
||||
public static char[] encodeHex(byte[] data, boolean toLowerCase) {
|
||||
return encodeHex(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符数组
|
||||
*
|
||||
* @param data byte[]
|
||||
* @param toDigits 用于控制输出的char[]
|
||||
* @return 十六进制char[]
|
||||
*/
|
||||
protected static char[] encodeHex(byte[] data, char[] toDigits) {
|
||||
int l = data.length;
|
||||
char[] out = new char[l << 1];
|
||||
// two characters form the hex value.
|
||||
for (int i = 0, j = 0; i < l; i++) {
|
||||
out[j++] = toDigits[(0xF0 & data[i]) >>> 4];
|
||||
out[j++] = toDigits[0x0F & data[i]];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符串
|
||||
*
|
||||
* @param data byte[]
|
||||
* @return 十六进制String
|
||||
*/
|
||||
public static String encodeHexString(byte[] data) {
|
||||
return encodeHexString(data, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符串
|
||||
*
|
||||
* @param data byte[]
|
||||
* @param toLowerCase <code>true</code> 传换成小写格式 , <code>false</code> 传换成大写格式
|
||||
* @return 十六进制String
|
||||
*/
|
||||
public static String encodeHexString(byte[] data, boolean toLowerCase) {
|
||||
return encodeHexString(data, toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字节数组转换为十六进制字符串
|
||||
*
|
||||
* @param data byte[]
|
||||
* @param toDigits 用于控制输出的char[]
|
||||
* @return 十六进制String
|
||||
*/
|
||||
protected static String encodeHexString(byte[] data, char[] toDigits) {
|
||||
return new String(encodeHex(data, toDigits));
|
||||
}
|
||||
|
||||
/**
|
||||
* 将十六进制字符数组转换为字节数组
|
||||
*
|
||||
* @param data 十六进制char[]
|
||||
* @return byte[]
|
||||
* @throws RuntimeException 如果源十六进制字符数组是一个奇怪的长度,将抛出运行时异常
|
||||
*/
|
||||
public static byte[] decodeHex(char[] data) {
|
||||
int len = data.length;
|
||||
|
||||
if ((len & 0x01) != 0) {
|
||||
throw new RuntimeException("Odd number of characters.");
|
||||
}
|
||||
|
||||
byte[] out = new byte[len >> 1];
|
||||
|
||||
// two characters form the hex value.
|
||||
for (int i = 0, j = 0; j < len; i++) {
|
||||
int f = toDigit(data[j], j) << 4;
|
||||
j++;
|
||||
f = f | toDigit(data[j], j);
|
||||
j++;
|
||||
out[i] = (byte) (f & 0xFF);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将十六进制字符转换成一个整数
|
||||
*
|
||||
* @param ch 十六进制char
|
||||
* @param index 十六进制字符在字符数组中的位置
|
||||
* @return 一个整数
|
||||
* @throws RuntimeException 当ch不是一个合法的十六进制字符时,抛出运行时异常
|
||||
*/
|
||||
protected static int toDigit(char ch, int index) {
|
||||
int digit = Character.digit(ch, 16);
|
||||
if (digit == -1) {
|
||||
throw new RuntimeException("Illegal hexadecimal character " + ch
|
||||
+ " at index " + index);
|
||||
}
|
||||
return digit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 数字字符串转ASCII码字符串
|
||||
*
|
||||
* @param String
|
||||
* 字符串
|
||||
* @return ASCII字符串
|
||||
*/
|
||||
public static String StringToAsciiString(String content) {
|
||||
String result = "";
|
||||
int max = content.length();
|
||||
for (int i = 0; i < max; i++) {
|
||||
char c = content.charAt(i);
|
||||
String b = Integer.toHexString(c);
|
||||
result = result + b;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 十六进制转字符串
|
||||
*
|
||||
* @param hexString
|
||||
* 十六进制字符串
|
||||
* @param encodeType
|
||||
* 编码类型4:Unicode,2:普通编码
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String hexStringToString(String hexString, int encodeType) {
|
||||
String result = "";
|
||||
int max = hexString.length() / encodeType;
|
||||
for (int i = 0; i < max; i++) {
|
||||
char c = (char) hexStringToAlgorism(hexString
|
||||
.substring(i * encodeType, (i + 1) * encodeType));
|
||||
result += c;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 十六进制字符串装十进制
|
||||
*
|
||||
* @param hex
|
||||
* 十六进制字符串
|
||||
* @return 十进制数值
|
||||
*/
|
||||
public static int hexStringToAlgorism(String hex) {
|
||||
hex = hex.toUpperCase();
|
||||
int max = hex.length();
|
||||
int result = 0;
|
||||
for (int i = max; i > 0; i--) {
|
||||
char c = hex.charAt(i - 1);
|
||||
int algorism = 0;
|
||||
if (c >= '0' && c <= '9') {
|
||||
algorism = c - '0';
|
||||
} else {
|
||||
algorism = c - 55;
|
||||
}
|
||||
result += Math.pow(16, max - i) * algorism;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 十六转二进制
|
||||
*
|
||||
* @param hex
|
||||
* 十六进制字符串
|
||||
* @return 二进制字符串
|
||||
*/
|
||||
public static String hexStringToBinary(String hex) {
|
||||
hex = hex.toUpperCase();
|
||||
String result = "";
|
||||
int max = hex.length();
|
||||
for (int i = 0; i < max; i++) {
|
||||
char c = hex.charAt(i);
|
||||
switch (c) {
|
||||
case '0':
|
||||
result += "0000";
|
||||
break;
|
||||
case '1':
|
||||
result += "0001";
|
||||
break;
|
||||
case '2':
|
||||
result += "0010";
|
||||
break;
|
||||
case '3':
|
||||
result += "0011";
|
||||
break;
|
||||
case '4':
|
||||
result += "0100";
|
||||
break;
|
||||
case '5':
|
||||
result += "0101";
|
||||
break;
|
||||
case '6':
|
||||
result += "0110";
|
||||
break;
|
||||
case '7':
|
||||
result += "0111";
|
||||
break;
|
||||
case '8':
|
||||
result += "1000";
|
||||
break;
|
||||
case '9':
|
||||
result += "1001";
|
||||
break;
|
||||
case 'A':
|
||||
result += "1010";
|
||||
break;
|
||||
case 'B':
|
||||
result += "1011";
|
||||
break;
|
||||
case 'C':
|
||||
result += "1100";
|
||||
break;
|
||||
case 'D':
|
||||
result += "1101";
|
||||
break;
|
||||
case 'E':
|
||||
result += "1110";
|
||||
break;
|
||||
case 'F':
|
||||
result += "1111";
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ASCII码字符串转数字字符串
|
||||
*
|
||||
* @param String
|
||||
* ASCII字符串
|
||||
* @return 字符串
|
||||
*/
|
||||
public static String AsciiStringToString(String content) {
|
||||
String result = "";
|
||||
int length = content.length() / 2;
|
||||
for (int i = 0; i < length; i++) {
|
||||
String c = content.substring(i * 2, i * 2 + 2);
|
||||
int a = hexStringToAlgorism(c);
|
||||
char b = (char) a;
|
||||
String d = String.valueOf(b);
|
||||
result += d;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将十进制转换为指定长度的十六进制字符串
|
||||
*
|
||||
* @param algorism
|
||||
* int 十进制数字
|
||||
* @param maxLength
|
||||
* int 转换后的十六进制字符串长度
|
||||
* @return String 转换后的十六进制字符串
|
||||
*/
|
||||
public static String algorismToHexString(int algorism, int maxLength) {
|
||||
String result = "";
|
||||
result = Integer.toHexString(algorism);
|
||||
|
||||
if (result.length() % 2 == 1) {
|
||||
result = "0" + result;
|
||||
}
|
||||
return patchHexString(result.toUpperCase(), maxLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* 字节数组转为普通字符串(ASCII对应的字符)
|
||||
*
|
||||
* @param bytearray
|
||||
* byte[]
|
||||
* @return String
|
||||
*/
|
||||
public static String byteToString(byte[] bytearray) {
|
||||
String result = "";
|
||||
char temp;
|
||||
|
||||
int length = bytearray.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
temp = (char) bytearray[i];
|
||||
result += temp;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 二进制字符串转十进制
|
||||
*
|
||||
* @param binary
|
||||
* 二进制字符串
|
||||
* @return 十进制数值
|
||||
*/
|
||||
public static int binaryToAlgorism(String binary) {
|
||||
int max = binary.length();
|
||||
int result = 0;
|
||||
for (int i = max; i > 0; i--) {
|
||||
char c = binary.charAt(i - 1);
|
||||
int algorism = c - '0';
|
||||
result += Math.pow(2, max - i) * algorism;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 十进制转换为十六进制字符串
|
||||
*
|
||||
* @param algorism
|
||||
* int 十进制的数字
|
||||
* @return String 对应的十六进制字符串
|
||||
*/
|
||||
public static String algorismToHEXString(int algorism) {
|
||||
String result = "";
|
||||
result = Integer.toHexString(algorism);
|
||||
|
||||
if (result.length() % 2 == 1) {
|
||||
result = "0" + result;
|
||||
|
||||
}
|
||||
result = result.toUpperCase();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* HEX字符串前补0,主要用于长度位数不足。
|
||||
*
|
||||
* @param str
|
||||
* String 需要补充长度的十六进制字符串
|
||||
* @param maxLength
|
||||
* int 补充后十六进制字符串的长度
|
||||
* @return 补充结果
|
||||
*/
|
||||
static public String patchHexString(String str, int maxLength) {
|
||||
String temp = "";
|
||||
for (int i = 0; i < maxLength - str.length(); i++) {
|
||||
temp = "0" + temp;
|
||||
}
|
||||
str = (temp + str).substring(0, maxLength);
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个字符串转换为int
|
||||
*
|
||||
* @param s
|
||||
* String 要转换的字符串
|
||||
* @param defaultInt
|
||||
* int 如果出现异常,默认返回的数字
|
||||
* @param radix
|
||||
* int 要转换的字符串是什么进制的,如16 8 10.
|
||||
* @return int 转换后的数字
|
||||
*/
|
||||
public static int parseToInt(String s, int defaultInt, int radix) {
|
||||
int i = 0;
|
||||
try {
|
||||
i = Integer.parseInt(s, radix);
|
||||
} catch (NumberFormatException ex) {
|
||||
i = defaultInt;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将一个十进制形式的数字字符串转换为int
|
||||
*
|
||||
* @param s
|
||||
* String 要转换的字符串
|
||||
* @param defaultInt
|
||||
* int 如果出现异常,默认返回的数字
|
||||
* @return int 转换后的数字
|
||||
*/
|
||||
public static int parseToInt(String s, int defaultInt) {
|
||||
int i = 0;
|
||||
try {
|
||||
i = Integer.parseInt(s);
|
||||
} catch (NumberFormatException ex) {
|
||||
i = defaultInt;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
/**
|
||||
* 十六进制串转化为byte数组
|
||||
*
|
||||
* @return the array of byte
|
||||
*/
|
||||
public static byte[] hexToByte(String hex)
|
||||
throws IllegalArgumentException {
|
||||
if (hex.length() % 2 != 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
char[] arr = hex.toCharArray();
|
||||
byte[] b = new byte[hex.length() / 2];
|
||||
for (int i = 0, j = 0, l = hex.length(); i < l; i++, j++) {
|
||||
String swap = "" + arr[i++] + arr[i];
|
||||
int byteint = Integer.parseInt(swap, 16) & 0xFF;
|
||||
b[j] = new Integer(byteint).byteValue();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字节数组转换为十六进制字符串
|
||||
*
|
||||
* @param b
|
||||
* byte[] 需要转换的字节数组
|
||||
* @return String 十六进制字符串
|
||||
*/
|
||||
public static String byteToHex(byte b[]) {
|
||||
if (b == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Argument b ( byte array ) is null! ");
|
||||
}
|
||||
String hs = "";
|
||||
String stmp = "";
|
||||
for (int n = 0; n < b.length; n++) {
|
||||
stmp = Integer.toHexString(b[n] & 0xff);
|
||||
if (stmp.length() == 1) {
|
||||
hs = hs + "0" + stmp;
|
||||
} else {
|
||||
hs = hs + stmp;
|
||||
}
|
||||
}
|
||||
return hs.toUpperCase();
|
||||
}
|
||||
|
||||
public static byte[] subByte(byte[] input, int startIndex, int length) {
|
||||
byte[] bt = new byte[length];
|
||||
for (int i = 0; i < length; i++) {
|
||||
bt[i] = input[i + startIndex];
|
||||
}
|
||||
return bt;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,166 @@
|
||||
package com.egzosn.pay.common.util.sign;
|
||||
|
||||
import com.egzosn.pay.common.util.sign.SM3.SM3Digest;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.PublicKey;
|
||||
import java.security.Signature;
|
||||
|
||||
public class SecureUtil {
|
||||
//日志
|
||||
protected static final Log log = LogFactory.getLog(SecureUtil.class);
|
||||
/**
|
||||
* 算法常量: SHA1
|
||||
*/
|
||||
private static final String ALGORITHM_SHA1 = "SHA-1";
|
||||
/**
|
||||
* 算法常量: SHA256
|
||||
*/
|
||||
private static final String ALGORITHM_SHA256 = "SHA-256";
|
||||
/**
|
||||
* 算法常量:SHA1withRSA
|
||||
*/
|
||||
private static final String BC_PROV_ALGORITHM_SHA1RSA = "SHA1withRSA";
|
||||
/**
|
||||
* 算法常量:SHA256withRSA
|
||||
*/
|
||||
private static final String BC_PROV_ALGORITHM_SHA256RSA = "SHA256withRSA";
|
||||
|
||||
/**
|
||||
* 获取摘要
|
||||
*
|
||||
* @param data 待计算的数据
|
||||
* @param algorithm 算法名
|
||||
* @return 计算结果
|
||||
*/
|
||||
private static byte[] digestByData (byte[] data,String algorithm) {
|
||||
MessageDigest md = null;
|
||||
try {
|
||||
md = MessageDigest.getInstance(algorithm);
|
||||
md.reset();
|
||||
md.update(data);
|
||||
return md.digest();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* sha1计算后进行16进制转换
|
||||
*
|
||||
* @param data 待计算的数据
|
||||
* @param encoding 编码
|
||||
* @return 计算结果
|
||||
*/
|
||||
public static byte[] sha1X16 (String data, String encoding) {
|
||||
try {
|
||||
byte[] bytes = digestByData(data.getBytes(encoding),ALGORITHM_SHA1);
|
||||
StringBuilder sha1StrBuff = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
|
||||
sha1StrBuff.append("0").append(
|
||||
Integer.toHexString(0xFF & bytes[i]));
|
||||
} else {
|
||||
sha1StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
}
|
||||
return sha1StrBuff.toString().getBytes(encoding);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* sha256计算后进行16进制转换
|
||||
*
|
||||
* @param data
|
||||
* 待计算的数据
|
||||
* @param encoding
|
||||
* 编码
|
||||
* @return 计算结果
|
||||
*/
|
||||
public static String sha256X16Str(String data, String encoding) {
|
||||
byte[] bytes =null;
|
||||
try {
|
||||
bytes = digestByData(data.getBytes(encoding),ALGORITHM_SHA1);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
StringBuilder sha256StrBuff = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
|
||||
sha256StrBuff.append("0").append(
|
||||
Integer.toHexString(0xFF & bytes[i]));
|
||||
} else {
|
||||
sha256StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
}
|
||||
return sha256StrBuff.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* SM3计算.
|
||||
*
|
||||
* @param data
|
||||
* 待计算的数据
|
||||
* @return 计算结果
|
||||
*/
|
||||
private static byte[] sm3(byte[] data) {
|
||||
|
||||
SM3Digest sm3 = new SM3Digest();
|
||||
sm3.update(data, 0, data.length);
|
||||
byte[] result = new byte[sm3.getDigestSize()];
|
||||
sm3.doFinal(result, 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* sm3计算后进行16进制转换
|
||||
*
|
||||
* @param data
|
||||
* 待计算的数据
|
||||
* @param encoding
|
||||
* 编码
|
||||
* @return 计算结果
|
||||
*/
|
||||
public static String sm3X16Str(String data, String encoding) {
|
||||
byte[] bytes = new byte[new SM3Digest().getDigestSize()];
|
||||
try {
|
||||
bytes = SecureUtil.sm3(data.getBytes(encoding));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
StringBuilder sm3StrBuff = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
|
||||
sm3StrBuff.append("0").append(
|
||||
Integer.toHexString(0xFF & bytes[i]));
|
||||
} else {
|
||||
sm3StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
}
|
||||
return sm3StrBuff.toString();
|
||||
}
|
||||
|
||||
public static boolean validateSignBySoft256(PublicKey publicKey, byte[] signData, byte[] srcData) throws Exception {
|
||||
Signature st = Signature.getInstance(BC_PROV_ALGORITHM_SHA256RSA, "BC");
|
||||
st.initVerify(publicKey);
|
||||
st.update(srcData);
|
||||
return st.verify(signData);
|
||||
}
|
||||
|
||||
public static boolean validateSignBySoft(PublicKey publicKey,
|
||||
byte[] signData, byte[] srcData) throws Exception {
|
||||
Signature st = Signature.getInstance(BC_PROV_ALGORITHM_SHA1RSA, "BC");
|
||||
st.initVerify(publicKey);
|
||||
st.update(srcData);
|
||||
return st.verify(signData);
|
||||
}
|
||||
}
|
||||
@@ -47,6 +47,29 @@ public class RSA{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA签名
|
||||
* @param content 待签名数据
|
||||
* @param privateKey 私钥
|
||||
* @return 签名值
|
||||
*/
|
||||
public static String sign(byte[] content,PrivateKey privateKey) {
|
||||
try {
|
||||
|
||||
java.security.Signature signature = java.security.Signature.getInstance(privateKey.getAlgorithm());
|
||||
|
||||
signature.initSign(privateKey);
|
||||
signature.update(content);
|
||||
|
||||
byte[] signed = signature.sign();
|
||||
|
||||
return Base64.encode(signed);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* RSA签名
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
package com.egzosn.pay.common.util.sign.encrypt;/**
|
||||
* Description:
|
||||
* author: Fuzx
|
||||
* date: 2017/11/27 0027
|
||||
*/
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
|
||||
/**
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* @create 2017 2017/11/27 0027
|
||||
*/
|
||||
public class SHA256 {
|
||||
//日志
|
||||
protected static final Log log = LogFactory.getLog(SHA256.class);
|
||||
|
||||
/**
|
||||
* 算法常量: SHA256
|
||||
*/
|
||||
private static final String ALGORITHM_SHA256 = "SHA-256";
|
||||
/**
|
||||
* sha256计算后进行16进制转换
|
||||
*
|
||||
* @param data
|
||||
* 待计算的数据
|
||||
* @param encoding
|
||||
* 编码
|
||||
* @return 计算结果
|
||||
*/
|
||||
public static byte[] sha256X16(String data, String encoding) {
|
||||
byte[] bytes = sha256(data, encoding);
|
||||
StringBuilder sha256StrBuff = new StringBuilder();
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
if (Integer.toHexString(0xFF & bytes[i]).length() == 1) {
|
||||
sha256StrBuff.append("0").append(
|
||||
Integer.toHexString(0xFF & bytes[i]));
|
||||
} else {
|
||||
sha256StrBuff.append(Integer.toHexString(0xFF & bytes[i]));
|
||||
}
|
||||
}
|
||||
try {
|
||||
return sha256StrBuff.toString().getBytes(encoding);
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* sha256计算
|
||||
*
|
||||
* @param datas
|
||||
* 待计算的数据
|
||||
* @param encoding
|
||||
* 字符集编码
|
||||
* @return
|
||||
*/
|
||||
private static byte[] sha256(String datas, String encoding) {
|
||||
try {
|
||||
return sha256(datas.getBytes(encoding));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error("SHA256计算失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* sha256计算.
|
||||
*
|
||||
* @param data
|
||||
* 待计算的数据
|
||||
* @return 计算结果
|
||||
*/
|
||||
private static byte[] sha256(byte[] data) {
|
||||
MessageDigest md = null;
|
||||
try {
|
||||
md = MessageDigest.getInstance(ALGORITHM_SHA256);
|
||||
md.reset();
|
||||
md.update(data);
|
||||
return md.digest();
|
||||
} catch (Exception e) {
|
||||
log.error("SHA256计算失败", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -79,6 +79,11 @@
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.8.4</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.egzosn</groupId>
|
||||
<artifactId>pay-java-union</artifactId>
|
||||
<version>2.0.5-SNAPSHOT</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<profiles>
|
||||
|
||||
@@ -4,15 +4,18 @@ package com.egzosn.pay.demo.controller;
|
||||
|
||||
import com.egzosn.pay.ali.bean.AliTransactionType;
|
||||
import com.egzosn.pay.common.api.Callback;
|
||||
import com.egzosn.pay.common.api.PayConfigStorage;
|
||||
import com.egzosn.pay.common.bean.*;
|
||||
import com.egzosn.pay.common.util.MatrixToImageWriter;
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
import com.egzosn.pay.demo.entity.ApyAccount;
|
||||
import com.egzosn.pay.demo.entity.PayType;
|
||||
import com.egzosn.pay.demo.request.QueryOrder;
|
||||
import com.egzosn.pay.demo.service.ApyAccountService;
|
||||
import com.egzosn.pay.demo.service.PayResponse;
|
||||
import com.egzosn.pay.demo.entity.PayType;
|
||||
import com.egzosn.pay.common.api.PayConfigStorage;
|
||||
import com.egzosn.pay.union.api.UnionPayService;
|
||||
import com.egzosn.pay.union.enums.UnionTransactionType;
|
||||
import com.egzosn.pay.union.request.UnionQueryOrder;
|
||||
import com.egzosn.pay.wx.bean.WxTransactionType;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
@@ -300,6 +303,19 @@ public class PayController {
|
||||
PayResponse payResponse = service.getPayResponse(order.getPayId());
|
||||
return payResponse.getService().query(order.getTradeNo(), order.getOutTradeNo());
|
||||
}
|
||||
/**
|
||||
* 查询
|
||||
*
|
||||
* @param order 订单的请求体
|
||||
* @return 返回查询回来的结果集,支付方原值返回
|
||||
*/
|
||||
@RequestMapping("unionRefundOrConsumeUndo")
|
||||
public Map<String, Object> unionQuery(UnionQueryOrder order,String transactionType) {
|
||||
PayResponse payResponse = service.getPayResponse(order.getPayId());
|
||||
UnionPayService service = (UnionPayService)payResponse.getService();
|
||||
|
||||
return service.unionRefundOrConsumeUndo(order,UnionTransactionType.valueOf(transactionType));
|
||||
}
|
||||
|
||||
/**
|
||||
* 交易关闭接口
|
||||
|
||||
@@ -81,6 +81,22 @@ public class ApyAccountRepository {
|
||||
apyAccount3.setMsgType(MsgType.xml);
|
||||
apyAccounts.put(apyAccount3.getPayId(), apyAccount3);
|
||||
|
||||
ApyAccount apyAccount4 = new ApyAccount();
|
||||
apyAccount4.setPayId(4);
|
||||
apyAccount4.setPartner("777290058110097");
|
||||
// apyAccount4.setAppid("777290058110097");
|
||||
apyAccount4.setPublicKey("");
|
||||
apyAccount4.setPrivateKey("000000");
|
||||
apyAccount4.setNotifyUrl("http://sailinmu.iok.la:19088/backRcvResponse");
|
||||
// 无需同步回调可不填 app填这个就可以
|
||||
apyAccount4.setReturnUrl("http://sailinmu.iok.la:19088/backRcvResponse");
|
||||
apyAccount4.setSeller("");
|
||||
apyAccount4.setInputCharset("UTF-8");
|
||||
apyAccount4.setSignType(SignUtils.RSA.name());
|
||||
apyAccount4.setPayType(PayType.unionPay);
|
||||
apyAccount4.setMsgType(MsgType.json);
|
||||
apyAccounts.put(apyAccount4.getPayId(), apyAccount3);
|
||||
|
||||
}
|
||||
//_____________________________________________________________
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ import com.egzosn.pay.ali.bean.AliTransactionType;
|
||||
import com.egzosn.pay.common.api.PayService;
|
||||
import com.egzosn.pay.common.bean.BasePayType;
|
||||
import com.egzosn.pay.common.bean.TransactionType;
|
||||
import com.egzosn.pay.demo.service.handler.FuiouPayMessageHandler;
|
||||
import com.egzosn.pay.fuiou.api.FuiouPayConfigStorage;
|
||||
import com.egzosn.pay.fuiou.api.FuiouPayService;
|
||||
import com.egzosn.pay.fuiou.bean.FuiouTransactionType;
|
||||
import com.egzosn.pay.fuiou.api.FuiouPayConfigStorage;
|
||||
import com.egzosn.pay.fuiou.api.FuiouPayService;
|
||||
import com.egzosn.pay.union.api.UnionPayConfigStorage;
|
||||
import com.egzosn.pay.union.api.UnionPayService;
|
||||
import com.egzosn.pay.union.enums.UnionTransactionType;
|
||||
import com.egzosn.pay.wx.api.WxPayConfigStorage;
|
||||
import com.egzosn.pay.wx.api.WxPayService;
|
||||
import com.egzosn.pay.wx.bean.WxTransactionType;
|
||||
@@ -144,6 +144,29 @@ public enum PayType implements BasePayType {
|
||||
}
|
||||
|
||||
|
||||
},unionPay{
|
||||
|
||||
@Override
|
||||
public PayService getPayService(ApyAccount apyAccount) {
|
||||
UnionPayConfigStorage unionPayConfigStorage = new UnionPayConfigStorage();
|
||||
unionPayConfigStorage.setKeyPublic(apyAccount.getPublicKey());
|
||||
unionPayConfigStorage.setKeyPrivate(apyAccount.getPrivateKey());
|
||||
unionPayConfigStorage.setNotifyUrl(apyAccount.getNotifyUrl());
|
||||
unionPayConfigStorage.setReturnUrl(apyAccount.getReturnUrl());
|
||||
unionPayConfigStorage.setSignType(apyAccount.getSignType());
|
||||
unionPayConfigStorage.setPayType(apyAccount.getPayType().toString());
|
||||
unionPayConfigStorage.setMsgType(apyAccount.getMsgType());
|
||||
unionPayConfigStorage.setInputCharset(apyAccount.getInputCharset());
|
||||
unionPayConfigStorage.setTest(apyAccount.isTest());
|
||||
return new UnionPayService(unionPayConfigStorage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransactionType getTransactionType(String transactionType) {
|
||||
return UnionTransactionType.valueOf(transactionType);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
public abstract PayService getPayService(ApyAccount apyAccount);
|
||||
|
||||
@@ -1,21 +1,15 @@
|
||||
package com.egzosn.pay.demo.service;
|
||||
|
||||
import com.egzosn.pay.common.api.PayMessageRouter;
|
||||
import com.egzosn.pay.common.http.HttpConfigStorage;
|
||||
import com.egzosn.pay.demo.service.handler.FuiouPayMessageHandler;
|
||||
import com.egzosn.pay.demo.service.handler.YouDianPayMessageHandler;
|
||||
import com.egzosn.pay.demo.service.interceptor.AliPayMessageInterceptor;
|
||||
import com.egzosn.pay.demo.entity.ApyAccount;
|
||||
import com.egzosn.pay.demo.entity.PayType;
|
||||
import com.egzosn.pay.demo.service.handler.AliPayMessageHandler;
|
||||
import com.egzosn.pay.demo.service.handler.FuiouPayMessageHandler;
|
||||
import com.egzosn.pay.demo.service.handler.WxPayMessageHandler;
|
||||
import com.egzosn.pay.demo.service.handler.YouDianPayMessageHandler;
|
||||
import com.egzosn.pay.demo.service.interceptor.AliPayMessageInterceptor;
|
||||
import com.egzosn.pay.common.api.PayConfigStorage;
|
||||
import com.egzosn.pay.common.api.PayMessageHandler;
|
||||
import com.egzosn.pay.common.api.PayMessageRouter;
|
||||
import com.egzosn.pay.common.api.PayService;
|
||||
import com.egzosn.pay.common.bean.MsgType;
|
||||
import com.egzosn.pay.common.http.HttpConfigStorage;
|
||||
import com.egzosn.pay.demo.entity.ApyAccount;
|
||||
import com.egzosn.pay.demo.entity.PayType;
|
||||
import com.egzosn.pay.demo.service.handler.*;
|
||||
import com.egzosn.pay.demo.service.interceptor.AliPayMessageInterceptor;
|
||||
import com.egzosn.pay.demo.service.interceptor.YoudianPayMessageInterceptor;
|
||||
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
|
||||
|
||||
@@ -116,7 +110,12 @@ public class PayResponse {
|
||||
.payType(PayType.fuiou.name())
|
||||
.handler(autowire(new FuiouPayMessageHandler(payId)))
|
||||
.end()
|
||||
|
||||
.rule()
|
||||
.async(false)
|
||||
.msgType(MsgType.json.name())
|
||||
.payType(PayType.unionPay.name())
|
||||
.handler(autowire(new UnionPayMessageHandler(payId)))
|
||||
.end()
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.egzosn.pay.demo.service.handler;
|
||||
|
||||
import com.egzosn.pay.common.api.PayService;
|
||||
import com.egzosn.pay.common.bean.PayMessage;
|
||||
import com.egzosn.pay.common.bean.PayOutMessage;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
create 2017 2017/11/4 0004
|
||||
* </pre>
|
||||
*/
|
||||
public class UnionPayMessageHandler extends BasePayMessageHandler {
|
||||
|
||||
|
||||
|
||||
|
||||
public UnionPayMessageHandler (Integer payId) {
|
||||
super(payId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PayOutMessage handle(PayMessage payMessage, Map<String, Object> context, PayService payService) throws PayErrorException {
|
||||
//交易状态
|
||||
if ("0000".equals(payMessage.getPayMessage().get("order_pay_code"))){
|
||||
/////这里进行成功的处理
|
||||
|
||||
return PayOutMessage.JSON().content("success","成功").build();
|
||||
}
|
||||
|
||||
return PayOutMessage.JSON().content("fail", "失败").build();
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,8 @@ package com.egzosn.pay.fuiou.api;
|
||||
import com.egzosn.pay.common.api.BasePayConfigStorage;
|
||||
|
||||
/**
|
||||
* @author Fuzx
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
* create 2017 2017/1/16 0016
|
||||
* </pre>
|
||||
|
||||
@@ -20,8 +20,9 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Fuzx
|
||||
* <pre>
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
* create 2017 2017/1/16 0016
|
||||
* </pre>
|
||||
*/
|
||||
|
||||
@@ -4,8 +4,11 @@ import com.egzosn.pay.common.bean.CurType;
|
||||
|
||||
/**
|
||||
* 货币类型
|
||||
* @author Fuzx
|
||||
* create 2017 2017/1/24 0024
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
* create 2017 2017/1/16 0016
|
||||
* </pre>
|
||||
*/
|
||||
public enum FuiouCurType implements CurType {
|
||||
|
||||
|
||||
@@ -4,8 +4,11 @@ import com.egzosn.pay.common.bean.TransactionType;
|
||||
|
||||
/**
|
||||
* 支付类型
|
||||
* @author Fuzx
|
||||
* create 2017 2017/1/24 0024
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
* create 2017 2017/1/16 0016
|
||||
* </pre>
|
||||
*/
|
||||
public enum FuiouTransactionType implements TransactionType {
|
||||
B2B("B2B"),
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
<artifactId>pay-java-common</artifactId>
|
||||
</dependency>
|
||||
<!-- /pay-java -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-debug-jdk15on</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
69
pay-java-union/resource/acp_sdk.properties
Normal file
69
pay-java-union/resource/acp_sdk.properties
Normal file
@@ -0,0 +1,69 @@
|
||||
##############SDK配置文件(证书方式签名)################
|
||||
# 说明:
|
||||
# 1. 使用时请删除后缀的“.证书”,并将此文件复制到src文件夹下替换原来的acp_sdk.properties。
|
||||
# 2. 具体配置项请根据注释修改。
|
||||
#
|
||||
################################################
|
||||
|
||||
##########################入网测试环境交易发送地址(线上测试需要使用生产环境交易请求地址)#############################
|
||||
|
||||
##交易请求地址
|
||||
acpsdk.frontTransUrl=https://gateway.test.95516.com/gateway/api/frontTransReq.do
|
||||
acpsdk.backTransUrl=https://gateway.test.95516.com/gateway/api/backTransReq.do
|
||||
acpsdk.singleQueryUrl=https://gateway.test.95516.com/gateway/api/queryTrans.do
|
||||
acpsdk.batchTransUrl=https://gateway.test.95516.com/gateway/api/batchTrans.do
|
||||
acpsdk.fileTransUrl=https://filedownload.test.95516.com/
|
||||
acpsdk.appTransUrl=https://gateway.test.95516.com/gateway/api/appTransReq.do
|
||||
acpsdk.cardTransUrl=https://gateway.test.95516.com/gateway/api/cardTransReq.do
|
||||
|
||||
#以下缴费产品使用,其余产品用不到
|
||||
acpsdk.jfFrontTransUrl=https://gateway.test.95516.com/jiaofei/api/frontTransReq.do
|
||||
acpsdk.jfBackTransUrl=https://gateway.test.95516.com/jiaofei/api/backTransReq.do
|
||||
acpsdk.jfSingleQueryUrl=https://gateway.test.95516.com/jiaofei/api/queryTrans.do
|
||||
acpsdk.jfCardTransUrl=https://gateway.test.95516.com/jiaofei/api/cardTransReq.do
|
||||
acpsdk.jfAppTransUrl=https://gateway.test.95516.com/jiaofei/api/appTransReq.do
|
||||
|
||||
########################################################################
|
||||
|
||||
# 报文版本号,固定5.1.0,请勿改动
|
||||
acpsdk.version=5.1.0
|
||||
|
||||
# 签名方式,证书方式固定01,请勿改动
|
||||
acpsdk.signMethod=01
|
||||
|
||||
# 是否验证验签证书的CN,测试环境请设置false,生产环境请设置true。非false的值默认都当true处理。
|
||||
acpsdk.ifValidateCNName=false
|
||||
|
||||
# 是否验证https证书,测试环境请设置false,生产环境建议优先尝试true,不行再false。非true的值默认都当false处理。
|
||||
acpsdk.ifValidateRemoteCert=false
|
||||
|
||||
#后台通知地址,填写接收银联后台通知的地址,必须外网能访问
|
||||
#acpsdk.backUrl=http://222.222.222.222:8080/ACPSample_B2C/backRcvResponse
|
||||
acpsdk.backUrl=http://sailinmu.iok.la:19088/backRcvResponse
|
||||
|
||||
#前台通知地址,填写处理银联前台通知的地址,必须外网能访问
|
||||
acpsdk.frontUrl=http://sailinmu.iok.la:19088/frontRcvResponse
|
||||
|
||||
#########################入网测试环境签名证书配置 ################################
|
||||
# 多证书的情况证书路径为代码指定,可不对此块做配置。
|
||||
# 签名证书路径,必须使用绝对路径,如果不想使用绝对路径,可以自行实现相对路径获取证书的方法;测试证书所有商户共用开发包中的测试签名证书,生产环境请从cfca下载得到。
|
||||
# windows样例:
|
||||
acpsdk.signCert.path=D:/certs/acp_test_sign.pfx
|
||||
# linux样例(注意:在linux下读取证书需要保证证书有被应用读的权限)(后续其他路径配置也同此条说明)
|
||||
#acpsdk.signCert.path=/SERVICE01/usr/ac_frnas/conf/ACPtest/acp_test_sign.pfx
|
||||
|
||||
# 签名证书密码,测试环境固定000000,生产环境请修改为从cfca下载的正式证书的密码,正式环境证书密码位数需小于等于6位,否则上传到商户服务网站会失败
|
||||
acpsdk.signCert.pwd=000000
|
||||
# 签名证书类型,固定不需要修改
|
||||
acpsdk.signCert.type=PKCS12
|
||||
|
||||
##########################加密证书配置################################
|
||||
# 敏感信息加密证书路径(商户号开通了商户对敏感信息加密的权限,需要对 卡号accNo,pin和phoneNo,cvn2,expired加密(如果这些上送的话),对敏感信息加密使用)
|
||||
acpsdk.encryptCert.path=d:/certs/acp_test_enc.cer
|
||||
|
||||
##########################验签证书配置################################
|
||||
# 验签中级证书路径(银联提供)
|
||||
acpsdk.middleCert.path=D:/certs/acp_test_middle.cer
|
||||
# 验签根证书路径(银联提供)
|
||||
acpsdk.rootCert.path=D:/certs/acp_test_root.cer
|
||||
|
||||
25
pay-java-union/resource/acp_test_enc.cer
Normal file
25
pay-java-union/resource/acp_test_enc.cer
Normal file
@@ -0,0 +1,25 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEQzCCAyugAwIBAgIFEAJkkicwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMC
|
||||
Q04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhv
|
||||
cml0eTEXMBUGA1UEAxMOQ0ZDQSBURVNUIE9DQTEwHhcNMTUxMjE1MDkxMTM1WhcN
|
||||
MTcxMjE1MDkxMTM1WjCBgTELMAkGA1UEBhMCY24xFzAVBgNVBAoTDkNGQ0EgVEVT
|
||||
VCBPQ0ExMRIwEAYDVQQLEwlDRkNBIFRFU1QxFDASBgNVBAsTC0VudGVycHJpc2Vz
|
||||
MS8wLQYDVQQDFCYwNDFAWjIwMTQtMTEtMTFAMDAwNDAwMDA6U0lHTkAwMDAwMDAw
|
||||
NTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANHnoPx0JZKZmFjIURxN
|
||||
AbLlWAw2jiFFWBnDF2MIGkya2r0fGiR0knq8zkKUnoIyC+tzEiOavniQaSu0ucuv
|
||||
/V4ugz66PSRxw1gaPcR2dDVdgojF00TcewxlJEA65fK3eKhUYfC3NbRaVQOMMdwv
|
||||
7nNEvzxvdExE47ceMya7FmsUPyLFu9X++chFQiYfr8nH+wdDeYo8w8vCX+Jd2vRu
|
||||
qDOah29CQfkAmXsx3D68zg0q4AjlLI1t5gLKiU5YoG6yWrigPyreEHh716rV8HkT
|
||||
jGWx3cxF/HsLZ/E4SgIr5yIZA6qw8RFqaSXuyw3iDrNf6aSJGO0GKlvxnvD20oGR
|
||||
JokCAwEAAaOB6TCB5jAfBgNVHSMEGDAWgBTPcJ1h6518Lrj3ywJA9wmd/jN0gDBI
|
||||
BgNVHSAEQTA/MD0GCGCBHIbvKgEBMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cu
|
||||
Y2ZjYS5jb20uY24vdXMvdXMtMTQuaHRtMDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6
|
||||
Ly91Y3JsLmNmY2EuY29tLmNuL1JTQS9jcmw0NTE3LmNybDALBgNVHQ8EBAMCA+gw
|
||||
HQYDVR0OBBYEFGjriHHUE1MnYX7H6GrFi+8R2zmUMBMGA1UdJQQMMAoGCCsGAQUF
|
||||
BwMCMA0GCSqGSIb3DQEBBQUAA4IBAQAjsN0fyDqcxS9YKMpY3CIdlarCjvnus+wS
|
||||
ExjNnPv7n2urqhz2Jf3yJuhxVVPzdgKT51C2UiR+/i1OJPWFx0IUos/v8js/TM5j
|
||||
mTdPkBsRSxSDieHHiuE1nPUwGXUEO7mlOVkkzmLI75bJ86foxNflbQCF0+VvpMe7
|
||||
KwQoNOR8DxIBxHdlsjSxE2RKM/ftXLhptrK4GK3K4FAcSiqBMEn5PF/5V9mHp5N6
|
||||
3LdkMYqBj4pRcy8vrclucq99b2glmMLw7CI6Kxu22WVoRnZESjcgXiMVLLe+qy55
|
||||
0pWcZ2BChS7Ln19tj49LnS3vFp6xf4qNSqxEBaQuNLEx0ObjI6pz
|
||||
-----END CERTIFICATE-----
|
||||
23
pay-java-union/resource/acp_test_middle.cer
Normal file
23
pay-java-union/resource/acp_test_middle.cer
Normal file
@@ -0,0 +1,23 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDzjCCAragAwIBAgIKGNDz/H99Hd/CxjANBgkqhkiG9w0BAQUFADBZMQswCQYD
|
||||
VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g
|
||||
QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODMwMDMx
|
||||
NDMzWhcNMzEwNTExMDMxNDMzWjBYMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp
|
||||
bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRcwFQYDVQQDEw5D
|
||||
RkNBIFRFU1QgT0NBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALiL
|
||||
J/BrdvHSbXNfLIMTwUg9tDtVjMRGXOl6aZnu9IpxjI5SMUJ4hVwgJnmbTokxs6GF
|
||||
IXKsCLSm5H1jHLI22ysc/ltByEybLWj5jjJuC9+Uknbl3/Ls1RBG6MogUCqZckuo
|
||||
hKrf5DmlV3C/jVLxGn3pUeanvmqVUi4TKpXxgm5QqKSPF8VtQY4qCpNcQwwZqbMr
|
||||
D+IfJtfpGAeVrP+Kg6i1t65seeEnVSaLhqpRUDU0PTblOuUv3OhiKJWA3cYWxUrg
|
||||
7U7SIHNJLSEUWmjy4mKty+g7Cnjzt29F9qXFb6oB2mR8yt4GHCilw1Rc5RBXY63H
|
||||
eTuOwdtGE3M2p7Q++OECAwEAAaOBmDCBlTAfBgNVHSMEGDAWgBR03sWNCn0QGqpp
|
||||
g1tNIc6Gm8xxODAMBgNVHRMEBTADAQH/MDgGA1UdHwQxMC8wLaAroCmGJ2h0dHA6
|
||||
Ly8yMTAuNzQuNDIuMy90ZXN0cmNhL1JTQS9jcmwxLmNybDALBgNVHQ8EBAMCAQYw
|
||||
HQYDVR0OBBYEFM9wnWHrnXwuuPfLAkD3CZ3+M3SAMA0GCSqGSIb3DQEBBQUAA4IB
|
||||
AQC0JOazrbkk0XMxMMeBCc3lgBId1RjQLgWUZ7zaUISpPstGIrE5A9aB6Ppq0Sxl
|
||||
pt2gkFhPEKUqgOFN1CzCDEbP3n4H0chqK1DOMrgTCD8ID5UW+ECTYNe35rZ+1JiF
|
||||
lOPEhFL3pv6XSkiKTfDnjum8+wFwUBGlfoWK1Hcx0P2Hk1jcZZKwGTx1IAkesF83
|
||||
pufhxHE2Ur7W4d4tfp+eC7XXcA91pdd+VUrAfkj9eKHcDEYZz66HvHzmt6rtJVBa
|
||||
pwrtCi9pW3rcm8c/1jSnEETZIaokai0fD7260h/LkD/GrNCibSWxFj1CqyP9Y5Yv
|
||||
cj6aA5LnUcJYeNkrQ3V4XvVc
|
||||
-----END CERTIFICATE-----
|
||||
22
pay-java-union/resource/acp_test_root.cer
Normal file
22
pay-java-union/resource/acp_test_root.cer
Normal file
@@ -0,0 +1,22 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDkzCCAnugAwIBAgIKUhN+zB19hbc65jANBgkqhkiG9w0BAQUFADBZMQswCQYD
|
||||
VQQGEwJDTjEwMC4GA1UEChMnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24g
|
||||
QXV0aG9yaXR5MRgwFgYDVQQDEw9DRkNBIFRFU1QgQ1MgQ0EwHhcNMTIwODI5MDUw
|
||||
MTI5WhcNMzIwODI5MDUwMTI5WjBZMQswCQYDVQQGEwJDTjEwMC4GA1UEChMnQ2hp
|
||||
bmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRgwFgYDVQQDEw9D
|
||||
RkNBIFRFU1QgQ1MgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
|
||||
rMJGruH6rOBPFxUI7T1ybydSRRtOM1xvkVjQNX0qmYir8feE6Tb0ctgtKR7a20DI
|
||||
YCj9kZ5ANBQqjRcj3Soq9XH3cirqhYHJ723OKyTpS0RPQ0N6vtVt3P5JQ+ztjWHd
|
||||
qIbbTOQ6O024TGTiqi6uHgMuz9/OVur81X3a5YVkK7jFeZ9o8cTcvQxD853/1sgZ
|
||||
QcmR9aUSw0RXH4XFLTrn7n4QSfWKiNotlD8Ag5gS1pH9ONUb6nGkMn3gh1xfJqjm
|
||||
ONMSknPXTGiNpXtqvYi8oIvByVCbUDO59IwPP1r1SYyE3P8Nr7DdQRu0KQSdXLoG
|
||||
iugSR3fn+toObVAQmplDAgMBAAGjXTBbMB8GA1UdIwQYMBaAFHTexY0KfRAaqmmD
|
||||
W00hzoabzHE4MAwGA1UdEwQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBR0
|
||||
3sWNCn0QGqppg1tNIc6Gm8xxODANBgkqhkiG9w0BAQUFAAOCAQEAM0eTkM35D4hj
|
||||
RlGC63wY0h++wVPUvOrObqAVBbzEEQ7ScBienmeY8Q6lWMUTXM9ALibZklpJPcJv
|
||||
3ntht7LL6ztd4wdX7E9RzZCQnRvbL9A/BU3NxWdeSpCg/OyPod5oCKP+6Uc7kApi
|
||||
F9OtYNWnt3l2Zp/NiedzEQD8H4qEWQLAq+0dFo5BkfVhb/jPcktndpfPOuH1IMhP
|
||||
tVcvo6jpFHw4U/nP2Jv59osIE97KJz/SPt2JAYnZOlIDqWwp9/Afvt0/MDr8y0PK
|
||||
Q9c6eqIzBx7a9LpUTUl5u1jS+xSDZ/KF2lXnjwaFp7jICLWEMlBstCoogi7KwH9A
|
||||
LpJP7/dj9g==
|
||||
-----END CERTIFICATE-----
|
||||
0
pay-java-union/resource/acp_test_sign.pfx
Normal file
0
pay-java-union/resource/acp_test_sign.pfx
Normal file
@@ -0,0 +1,822 @@
|
||||
/**
|
||||
*
|
||||
* Licensed Property to China UnionPay Co., Ltd.
|
||||
*
|
||||
* (C) Copyright of China UnionPay Co., Ltd. 2010
|
||||
* All Rights Reserved.
|
||||
*
|
||||
*
|
||||
* Modification History:
|
||||
* =============================================================================
|
||||
* Author Date Description
|
||||
* ------------ ---------- ---------------------------------------------------
|
||||
* xshu 2014-05-28 证书工具类.
|
||||
* =============================================================================
|
||||
*/
|
||||
package com.egzosn.pay.union.SDK;
|
||||
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.security.*;
|
||||
import java.security.cert.*;
|
||||
import java.security.spec.RSAPublicKeySpec;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @ClassName: CertUtil
|
||||
* @Description: acpsdk证书工具类,主要用于对证书的加载和使用
|
||||
* @date 2016-7-22 下午2:46:20
|
||||
*
|
||||
*/
|
||||
public class CertUtil {
|
||||
//日志
|
||||
protected static final Log log = LogFactory.getLog(CertUtil.class);
|
||||
|
||||
public static final String UNIONPAY_CNNAME = "中国银联股份有限公司";
|
||||
|
||||
/** 证书容器,存储对商户请求报文签名私钥证书. */
|
||||
private static KeyStore keyStore = null;
|
||||
/** 敏感信息加密公钥证书 */
|
||||
private static X509Certificate encryptCert = null;
|
||||
/** 磁道加密公钥 */
|
||||
private static PublicKey encryptTrackKey = null;
|
||||
/** 验证银联返回报文签名证书. */
|
||||
private static X509Certificate validateCert = null;
|
||||
/** 验签中级证书 */
|
||||
private static X509Certificate middleCert = null;
|
||||
/** 验签根证书 */
|
||||
private static X509Certificate rootCert = null;
|
||||
/** 验证银联返回报文签名的公钥证书存储Map. */
|
||||
private static Map<String, X509Certificate> certMap = new HashMap<String, X509Certificate>();
|
||||
/** 商户私钥存储Map */
|
||||
private final static Map<String, KeyStore> keyStoreMap = new ConcurrentHashMap<String, KeyStore>();
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 请求报文签名(使用配置文件中配置的私钥证书或者对称密钥签名)<br>
|
||||
* 功能:对请求报文进行签名,并计算赋值certid,signature字段并返回<br>
|
||||
* @param reqData 请求报文map<br>
|
||||
* @param encoding 上送请求报文域encoding字段的值<br>
|
||||
* @return 签名后的map对象<br>
|
||||
*/
|
||||
public static Map<String, String> sign(Map<String, String> reqData,String encoding) {
|
||||
reqData = filterBlank(reqData);
|
||||
SDKUtils.signParams(reqData, encoding);
|
||||
return reqData;
|
||||
}
|
||||
/**
|
||||
* 过滤请求报文中的空字符串或者空字符串
|
||||
* @param contentData
|
||||
* @return
|
||||
*/
|
||||
public static Map<String, String> filterBlank(Map<String, String> contentData){
|
||||
Map<String, String> submitFromData = new HashMap<String, String>();
|
||||
Set<String> keyset = contentData.keySet();
|
||||
for(String key:keyset){
|
||||
String value = contentData.get(key);
|
||||
if (StringUtils.isNotBlank(value)) {
|
||||
// 对value值进行去除前后空处理
|
||||
submitFromData.put(key, value.trim());
|
||||
}
|
||||
}
|
||||
return submitFromData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化所有证书.
|
||||
*/
|
||||
private static void init() {
|
||||
try {
|
||||
addProvider();//向系统添加BC provider
|
||||
initSignCert();//初始化签名私钥证书
|
||||
initMiddleCert();//初始化验签证书的中级证书
|
||||
initRootCert();//初始化验签证书的根证书
|
||||
initEncryptCert();//初始化加密公钥
|
||||
initTrackKey();//构建磁道加密公钥
|
||||
initValidateCertFromDir();//初始化所有的验签证书
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
log.error("init失败。(如果是用对称密钥签名的可无视此异常。)", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加签名,验签,加密算法提供者
|
||||
*/
|
||||
private static void addProvider(){
|
||||
if (Security.getProvider("BC") == null) {
|
||||
log.info("add BC provider");
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
} else {
|
||||
Security.removeProvider("BC"); //解决eclipse调试时tomcat自动重新加载时,BC存在不明原因异常的问题。
|
||||
Security.addProvider(new BouncyCastleProvider());
|
||||
log.info("re-add BC provider");
|
||||
}
|
||||
// printSysInfo();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用配置文件acp_sdk.properties中配置的私钥路径和密码 加载签名证书
|
||||
*/
|
||||
private static void initSignCert() {
|
||||
if(!"01".equals(SDKConfig.getConfig().getSignMethod())){
|
||||
log.info("非rsa签名方式,不加载签名证书。");
|
||||
return;
|
||||
}
|
||||
if (SDKConfig.getConfig().getSignCertPath() == null
|
||||
|| SDKConfig.getConfig().getSignCertPwd() == null
|
||||
|| SDKConfig.getConfig().getSignCertType() == null) {
|
||||
log.error("WARN: " + SDKConfig.SDK_SIGNCERT_PATH + "或" + SDKConfig.SDK_SIGNCERT_PWD
|
||||
+ "或" + SDKConfig.SDK_SIGNCERT_TYPE + "为空。 停止加载签名证书。");
|
||||
return;
|
||||
}
|
||||
if (null != keyStore) {
|
||||
keyStore = null;
|
||||
}
|
||||
try {
|
||||
keyStore = getKeyInfo(SDKConfig.getConfig().getSignCertPath(),
|
||||
SDKConfig.getConfig().getSignCertPwd(), SDKConfig
|
||||
.getConfig().getSignCertType());
|
||||
log.info("InitSignCert Successful. CertId=["
|
||||
+ getSignCertId() + "]");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error("InitSignCert Error", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用配置文件acp_sdk.properties配置路径 加载敏感信息加密证书
|
||||
*/
|
||||
private static void initMiddleCert() {
|
||||
// log.info("加载中级证书==>"+SDKConfig.getConfig().getMiddleCertPath());
|
||||
if (!StringUtils.isEmpty(SDKConfig.getConfig().getMiddleCertPath())) {
|
||||
middleCert = initCert(SDKConfig.getConfig().getMiddleCertPath());
|
||||
log.info("Load MiddleCert Successful");
|
||||
} else {
|
||||
log.info("WARN: acpsdk.middle.path is empty");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用配置文件acp_sdk.properties配置路径 加载敏感信息加密证书
|
||||
*/
|
||||
private static void initRootCert() {
|
||||
// log.info("加载根证书==>"+SDKConfig.getConfig().getRootCertPath());
|
||||
if (!StringUtils.isEmpty(SDKConfig.getConfig().getRootCertPath())) {
|
||||
rootCert = initCert(SDKConfig.getConfig().getRootCertPath());
|
||||
log.info("Load RootCert Successful");
|
||||
} else {
|
||||
log.info("WARN: acpsdk.rootCert.path is empty");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用配置文件acp_sdk.properties配置路径 加载银联公钥上级证书(中级证书)
|
||||
*/
|
||||
private static void initEncryptCert() {
|
||||
// log.info("加载敏感信息加密证书==>"+SDKConfig.getConfig().getEncryptCertPath());
|
||||
if (!StringUtils.isEmpty(SDKConfig.getConfig().getEncryptCertPath())) {
|
||||
encryptCert = initCert(SDKConfig.getConfig().getEncryptCertPath());
|
||||
log.info("Load EncryptCert Successful");
|
||||
} else {
|
||||
log.info("WARN: acpsdk.encryptCert.path is empty");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用配置文件acp_sdk.properties配置路径 加载磁道公钥
|
||||
*/
|
||||
private static void initTrackKey() {
|
||||
if (!StringUtils.isEmpty(SDKConfig.getConfig().getEncryptTrackKeyModulus())
|
||||
&& !StringUtils.isEmpty(SDKConfig.getConfig().getEncryptTrackKeyExponent())) {
|
||||
encryptTrackKey = getPublicKey(SDKConfig.getConfig().getEncryptTrackKeyModulus(),
|
||||
SDKConfig.getConfig().getEncryptTrackKeyExponent());
|
||||
log.info("LoadEncryptTrackKey Successful");
|
||||
} else {
|
||||
log.info("WARN: acpsdk.encryptTrackKey.modulus or acpsdk.encryptTrackKey.exponent is empty");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用配置文件acp_sdk.properties配置路径 加载验证签名证书
|
||||
*/
|
||||
private static void initValidateCertFromDir() {
|
||||
if(!"01".equals(SDKConfig.getConfig().getSignMethod())){
|
||||
log.info("非rsa签名方式,不加载验签证书。");
|
||||
return;
|
||||
}
|
||||
certMap.clear();
|
||||
String dir = SDKConfig.getConfig().getValidateCertDir();
|
||||
log.info("加载验证签名证书目录==>" + dir +" 注:如果请求报文中version=5.1.0那么此验签证书目录使用不到,可以不需要设置(version=5.0.0必须设置)。");
|
||||
if (StringUtils.isEmpty(dir)) {
|
||||
log.error("WARN: acpsdk.validateCert.dir is empty");
|
||||
return;
|
||||
}
|
||||
CertificateFactory cf = null;
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
cf = CertificateFactory.getInstance("X.509", "BC");
|
||||
}catch (NoSuchProviderException e) {
|
||||
log.error("LoadVerifyCert Error: No BC Provider", e);
|
||||
return ;
|
||||
} catch (CertificateException e) {
|
||||
log.error("LoadVerifyCert Error", e);
|
||||
return ;
|
||||
}
|
||||
File fileDir = new File(dir);
|
||||
File[] files = fileDir.listFiles(new CerFilter());
|
||||
for (int i = 0; i < files.length; i++) {
|
||||
File file = files[i];
|
||||
try {
|
||||
in = new FileInputStream(file.getAbsolutePath());
|
||||
validateCert = (X509Certificate) cf.generateCertificate(in);
|
||||
if(validateCert == null) {
|
||||
log.error("Load verify cert error, " + file.getAbsolutePath() + " has error cert content.");
|
||||
continue;
|
||||
}
|
||||
certMap.put(validateCert.getSerialNumber().toString(),
|
||||
validateCert);
|
||||
// 打印证书加载信息,供测试阶段调试
|
||||
log.info("[" + file.getAbsolutePath() + "][CertId="
|
||||
+ validateCert.getSerialNumber().toString() + "]");
|
||||
} catch (CertificateException e) {
|
||||
log.error("LoadVerifyCert Error", e);
|
||||
e.printStackTrace();
|
||||
}catch (FileNotFoundException e) {
|
||||
log.error("LoadVerifyCert Error File Not Found", e);
|
||||
e.printStackTrace();
|
||||
}finally {
|
||||
if (null != in) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
log.error(e.toString());
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info("LoadVerifyCert Finish");
|
||||
}
|
||||
|
||||
/**
|
||||
* 用给定的路径和密码 加载签名证书,并保存到certKeyStoreMap
|
||||
*
|
||||
* @param certFilePath
|
||||
* @param certPwd
|
||||
*/
|
||||
private static void loadSignCert(String certFilePath, String certPwd) {
|
||||
KeyStore keyStore = null;
|
||||
try {
|
||||
keyStore = getKeyInfo(certFilePath, certPwd, "PKCS12");
|
||||
keyStoreMap.put(certFilePath, keyStore);
|
||||
log.info("LoadRsaCert Successful");
|
||||
} catch (IOException e) {
|
||||
log.error("LoadRsaCert Error", e);
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过证书路径初始化为公钥证书
|
||||
* @param path
|
||||
* @return
|
||||
*/
|
||||
private static X509Certificate initCert(String path) {
|
||||
X509Certificate encryptCertTemp = null;
|
||||
CertificateFactory cf = null;
|
||||
FileInputStream in = null;
|
||||
try {
|
||||
cf = CertificateFactory.getInstance("X.509", "BC");
|
||||
in = new FileInputStream(path);
|
||||
encryptCertTemp = (X509Certificate) cf.generateCertificate(in);
|
||||
// 打印证书加载信息,供测试阶段调试
|
||||
log.info("[" + path + "][CertId="
|
||||
+ encryptCertTemp.getSerialNumber().toString() + "]");
|
||||
} catch (CertificateException e) {
|
||||
log.error("InitCert Error", e);
|
||||
e.printStackTrace();
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
log.error("InitCert Error File Not Found", e);
|
||||
} catch (NoSuchProviderException e) {
|
||||
e.printStackTrace();
|
||||
log.error("LoadVerifyCert Error No BC Provider", e);
|
||||
} finally {
|
||||
if (null != in) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
log.error(e.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
return encryptCertTemp;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过keyStore 获取私钥签名证书PrivateKey对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static PrivateKey getSignCertPrivateKey() {
|
||||
try {
|
||||
Enumeration<String> aliasenum = keyStore.aliases();
|
||||
String keyAlias = null;
|
||||
if (aliasenum.hasMoreElements()) {
|
||||
keyAlias = aliasenum.nextElement();
|
||||
}
|
||||
PrivateKey privateKey = (PrivateKey) keyStore.getKey(keyAlias,
|
||||
SDKConfig.getConfig().getSignCertPwd().toCharArray());
|
||||
return privateKey;
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
log.error("getSignCertPrivateKey Error", e);
|
||||
return null;
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
log.error("getSignCertPrivateKey Error", e);
|
||||
return null;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
log.error("getSignCertPrivateKey Error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 通过指定路径的私钥证书 获取PrivateKey对象
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static PrivateKey getSignCertPrivateKeyByStoreMap(String certPath,
|
||||
String certPwd) {
|
||||
if (!keyStoreMap.containsKey(certPath)) {
|
||||
loadSignCert(certPath, certPwd);
|
||||
}
|
||||
try {
|
||||
Enumeration<String> aliasenum = keyStoreMap.get(certPath)
|
||||
.aliases();
|
||||
String keyAlias = null;
|
||||
if (aliasenum.hasMoreElements()) {
|
||||
keyAlias = aliasenum.nextElement();
|
||||
}
|
||||
PrivateKey privateKey = (PrivateKey) keyStoreMap.get(certPath)
|
||||
.getKey(keyAlias, certPwd.toCharArray());
|
||||
return privateKey;
|
||||
} catch (KeyStoreException e) {
|
||||
e.printStackTrace();
|
||||
log.error("getSignCertPrivateKeyByStoreMap Error", e);
|
||||
return null;
|
||||
} catch (UnrecoverableKeyException e) {
|
||||
e.printStackTrace();
|
||||
log.error("getSignCertPrivateKeyByStoreMap Error", e);
|
||||
return null;
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
log.error("getSignCertPrivateKeyByStoreMap Error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取敏感信息加密证书PublicKey
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static PublicKey getEncryptCertPublicKey() {
|
||||
if (null == encryptCert) {
|
||||
String path = SDKConfig.getConfig().getEncryptCertPath();
|
||||
if (!StringUtils.isEmpty(path)) {
|
||||
encryptCert = initCert(path);
|
||||
return encryptCert.getPublicKey();
|
||||
} else {
|
||||
log.error("acpsdk.encryptCert.path is empty");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return encryptCert.getPublicKey();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置敏感信息加密证书公钥
|
||||
*/
|
||||
public static void resetEncryptCertPublicKey() {
|
||||
encryptCert = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取磁道加密证书PublicKey
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static PublicKey getEncryptTrackPublicKey() {
|
||||
if (null == encryptTrackKey) {
|
||||
initTrackKey();
|
||||
}
|
||||
return encryptTrackKey;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过certId获取验签证书Map中对应证书PublicKey
|
||||
*
|
||||
* @param certId 证书物理序号
|
||||
* @return 通过证书编号获取到的公钥
|
||||
*/
|
||||
public static PublicKey getValidatePublicKey(String certId) {
|
||||
X509Certificate cf = null;
|
||||
if (certMap.containsKey(certId)) {
|
||||
// 存在certId对应的证书对象
|
||||
cf = certMap.get(certId);
|
||||
return cf.getPublicKey();
|
||||
} else {
|
||||
// 不存在则重新Load证书文件目录
|
||||
initValidateCertFromDir();
|
||||
if (certMap.containsKey(certId)) {
|
||||
// 存在certId对应的证书对象
|
||||
cf = certMap.get(certId);
|
||||
return cf.getPublicKey();
|
||||
} else {
|
||||
log.error("缺少certId=[" + certId + "]对应的验签证书.");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取配置文件acp_sdk.properties中配置的签名私钥证书certId
|
||||
*
|
||||
* @return 证书的物理编号
|
||||
*/
|
||||
public static String getSignCertId() {
|
||||
try {
|
||||
Enumeration<String> aliasenum = keyStore.aliases();
|
||||
String keyAlias = null;
|
||||
if (aliasenum.hasMoreElements()) {
|
||||
keyAlias = aliasenum.nextElement();
|
||||
}
|
||||
X509Certificate cert = (X509Certificate) keyStore
|
||||
.getCertificate(keyAlias);
|
||||
return cert.getSerialNumber().toString();
|
||||
} catch (Exception e) {
|
||||
log.error("getSignCertId Error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取敏感信息加密证书的certId
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getEncryptCertId() {
|
||||
if (null == encryptCert) {
|
||||
String path = SDKConfig.getConfig().getEncryptCertPath();
|
||||
if (!StringUtils.isEmpty(path)) {
|
||||
encryptCert = initCert(path);
|
||||
return encryptCert.getSerialNumber().toString();
|
||||
} else {
|
||||
log.error("acpsdk.encryptCert.path is empty");
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return encryptCert.getSerialNumber().toString();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将签名私钥证书文件读取为证书存储对象
|
||||
*
|
||||
* @param pfxkeyfile
|
||||
* 证书文件名
|
||||
* @param keypwd
|
||||
* 证书密码
|
||||
* @param type
|
||||
* 证书类型
|
||||
* @return 证书对象
|
||||
* @throws IOException
|
||||
*/
|
||||
private static KeyStore getKeyInfo(String pfxkeyfile, String keypwd,
|
||||
String type) throws IOException {
|
||||
log.info("加载签名证书==>" + pfxkeyfile);
|
||||
FileInputStream fis = null;
|
||||
try {
|
||||
KeyStore ks = KeyStore.getInstance(type, "BC");
|
||||
log.info("Load RSA CertPath=[" + pfxkeyfile + "],Pwd=["+ keypwd + "],type=["+type+"]");
|
||||
fis = new FileInputStream(pfxkeyfile);
|
||||
char[] nPassword = null;
|
||||
nPassword = null == keypwd || "".equals(keypwd.trim()) ? null: keypwd.toCharArray();
|
||||
if (null != ks) {
|
||||
ks.load(fis, nPassword);
|
||||
}
|
||||
return ks;
|
||||
} catch (Exception e) {
|
||||
log.error("getKeyInfo Error", e);
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
} finally {
|
||||
if(null!=fis)
|
||||
fis.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过签名私钥证书路径,密码获取私钥证书certId
|
||||
* @param certPath
|
||||
* @param certPwd
|
||||
* @return
|
||||
*/
|
||||
public static String getCertIdByKeyStoreMap(String certPath, String certPwd) {
|
||||
if (!keyStoreMap.containsKey(certPath)) {
|
||||
// 缓存中未查询到,则加载RSA证书
|
||||
loadSignCert(certPath, certPwd);
|
||||
}
|
||||
return getCertIdIdByStore(keyStoreMap.get(certPath));
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过keystore获取私钥证书的certId值
|
||||
* @param keyStore
|
||||
* @return
|
||||
*/
|
||||
private static String getCertIdIdByStore(KeyStore keyStore) {
|
||||
Enumeration<String> aliasenum = null;
|
||||
try {
|
||||
aliasenum = keyStore.aliases();
|
||||
String keyAlias = null;
|
||||
if (aliasenum.hasMoreElements()) {
|
||||
keyAlias = aliasenum.nextElement();
|
||||
}
|
||||
X509Certificate cert = (X509Certificate) keyStore
|
||||
.getCertificate(keyAlias);
|
||||
return cert.getSerialNumber().toString();
|
||||
} catch (KeyStoreException e) {
|
||||
log.error("getCertIdIdByStore Error", e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用模和指数生成RSA公钥 注意:此代码用了默认补位方式,为RSA/None/PKCS1Padding,不同JDK默认的补位方式可能不同
|
||||
*
|
||||
* @param modulus
|
||||
* 模
|
||||
* @param exponent
|
||||
* 指数
|
||||
* @return
|
||||
*/
|
||||
private static PublicKey getPublicKey(String modulus, String exponent) {
|
||||
try {
|
||||
BigInteger b1 = new BigInteger(modulus);
|
||||
BigInteger b2 = new BigInteger(exponent);
|
||||
KeyFactory keyFactory = KeyFactory.getInstance("RSA", "BC");
|
||||
RSAPublicKeySpec keySpec = new RSAPublicKeySpec(b1, b2);
|
||||
return keyFactory.generatePublic(keySpec);
|
||||
} catch (Exception e) {
|
||||
log.error("构造RSA公钥失败:" + e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将字符串转换为X509Certificate对象.
|
||||
*
|
||||
* @param x509CertString
|
||||
* @return
|
||||
*/
|
||||
public static X509Certificate genCertificateByStr(String x509CertString) {
|
||||
X509Certificate x509Cert = null;
|
||||
try {
|
||||
CertificateFactory cf = CertificateFactory.getInstance("X.509", "BC");
|
||||
InputStream tIn = new ByteArrayInputStream(
|
||||
x509CertString.getBytes("ISO-8859-1"));
|
||||
x509Cert = (X509Certificate) cf.generateCertificate(tIn);
|
||||
} catch (Exception e) {
|
||||
log.error("gen certificate error", e);
|
||||
}
|
||||
return x509Cert;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从配置文件acp_sdk.properties中获取验签公钥使用的中级证书
|
||||
* @return
|
||||
*/
|
||||
public static X509Certificate getMiddleCert() {
|
||||
if (null == middleCert) {
|
||||
String path = SDKConfig.getConfig().getMiddleCertPath();
|
||||
if (!StringUtils.isEmpty(path)) {
|
||||
initMiddleCert();
|
||||
} else {
|
||||
log.error(SDKConfig.SDK_MIDDLECERT_PATH + " not set in " + SDKConfig.FILE_NAME);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return middleCert;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从配置文件acp_sdk.properties中获取验签公钥使用的根证书
|
||||
* @return
|
||||
*/
|
||||
public static X509Certificate getRootCert() {
|
||||
if (null == rootCert) {
|
||||
String path = SDKConfig.getConfig().getRootCertPath();
|
||||
if (!StringUtils.isEmpty(path)) {
|
||||
initRootCert();
|
||||
} else {
|
||||
log.error(SDKConfig.SDK_ROOTCERT_PATH + " not set in " + SDKConfig.FILE_NAME);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return rootCert;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取证书的CN
|
||||
* @param aCert
|
||||
* @return
|
||||
*/
|
||||
private static String getIdentitiesFromCertficate(X509Certificate aCert) {
|
||||
String tDN = aCert.getSubjectDN().toString();
|
||||
String tPart = "";
|
||||
if ((tDN != null)) {
|
||||
String tSplitStr[] = tDN.substring(tDN.indexOf("CN=")).split("@");
|
||||
if (tSplitStr != null && tSplitStr.length > 2
|
||||
&& tSplitStr[2] != null)
|
||||
tPart = tSplitStr[2];
|
||||
}
|
||||
return tPart;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证书链。
|
||||
* @param cert
|
||||
* @return
|
||||
*/
|
||||
private static boolean verifyCertificateChain(X509Certificate cert){
|
||||
|
||||
if ( null == cert) {
|
||||
log.error("cert must Not null");
|
||||
return false;
|
||||
}
|
||||
|
||||
X509Certificate middleCert = CertUtil.getMiddleCert();
|
||||
if (null == middleCert) {
|
||||
log.error("middleCert must Not null");
|
||||
return false;
|
||||
}
|
||||
|
||||
X509Certificate rootCert = CertUtil.getRootCert();
|
||||
if (null == rootCert) {
|
||||
log.error("rootCert or cert must Not null");
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
|
||||
X509CertSelector selector = new X509CertSelector();
|
||||
selector.setCertificate(cert);
|
||||
|
||||
Set<TrustAnchor> trustAnchors = new HashSet<TrustAnchor>();
|
||||
trustAnchors.add(new TrustAnchor(rootCert, null));
|
||||
PKIXBuilderParameters pkixParams = new PKIXBuilderParameters(
|
||||
trustAnchors, selector);
|
||||
|
||||
Set<X509Certificate> intermediateCerts = new HashSet<X509Certificate>();
|
||||
intermediateCerts.add(rootCert);
|
||||
intermediateCerts.add(middleCert);
|
||||
intermediateCerts.add(cert);
|
||||
|
||||
pkixParams.setRevocationEnabled(false);
|
||||
|
||||
CertStore intermediateCertStore = CertStore.getInstance("Collection",
|
||||
new CollectionCertStoreParameters(intermediateCerts), "BC");
|
||||
pkixParams.addCertStore(intermediateCertStore);
|
||||
|
||||
CertPathBuilder builder = CertPathBuilder.getInstance("PKIX", "BC");
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
PKIXCertPathBuilderResult result = (PKIXCertPathBuilderResult) builder
|
||||
.build(pkixParams);
|
||||
log.info("verify certificate chain succeed.");
|
||||
return true;
|
||||
} catch (CertPathBuilderException e){
|
||||
log.error("verify certificate chain fail.", e);
|
||||
} catch (Exception e) {
|
||||
log.error("verify certificate chain exception: ", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查证书链
|
||||
*
|
||||
* @param cert
|
||||
* 待验证的证书
|
||||
* @return
|
||||
*/
|
||||
public static boolean verifyCertificate(X509Certificate cert) {
|
||||
|
||||
if ( null == cert) {
|
||||
log.error("cert must Not null");
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
cert.checkValidity();//验证有效期
|
||||
// cert.verify(middleCert.getPublicKey());
|
||||
if(!verifyCertificateChain(cert)){
|
||||
return false;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("verifyCertificate fail", e);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(SDKConfig.getConfig().isIfValidateCNName()){
|
||||
// 验证公钥是否属于银联
|
||||
if(!UNIONPAY_CNNAME.equals(CertUtil.getIdentitiesFromCertficate(cert))) {
|
||||
log.error("cer owner is not CUP:" + CertUtil.getIdentitiesFromCertficate(cert));
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// 验证公钥是否属于银联
|
||||
if(!UNIONPAY_CNNAME.equals(CertUtil.getIdentitiesFromCertficate(cert))
|
||||
&& !"00040000:SIGN".equals(CertUtil.getIdentitiesFromCertficate(cert))) {
|
||||
log.error("cer owner is not CUP:" + CertUtil.getIdentitiesFromCertficate(cert));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 打印系统环境信息
|
||||
*/
|
||||
private static void printSysInfo() {
|
||||
log.info("================= SYS INFO begin====================");
|
||||
log.info("os_name:" + System.getProperty("os.name"));
|
||||
log.info("os_arch:" + System.getProperty("os.arch"));
|
||||
log.info("os_version:" + System.getProperty("os.version"));
|
||||
log.info("java_vm_specification_version:"
|
||||
+ System.getProperty("java.vm.specification.version"));
|
||||
log.info("java_vm_specification_vendor:"
|
||||
+ System.getProperty("java.vm.specification.vendor"));
|
||||
log.info("java_vm_specification_name:"
|
||||
+ System.getProperty("java.vm.specification.name"));
|
||||
log.info("java_vm_version:"
|
||||
+ System.getProperty("java.vm.version"));
|
||||
log.info("java_vm_name:" + System.getProperty("java.vm.name"));
|
||||
log.info("java.version:" + System.getProperty("java.version"));
|
||||
log.info("java.vm.vendor=[" + System.getProperty("java.vm.vendor") + "]");
|
||||
log.info("java.version=[" + System.getProperty("java.version") + "]");
|
||||
// printProviders();
|
||||
log.info("================= SYS INFO end=====================");
|
||||
}
|
||||
|
||||
/**
|
||||
* 打jre中印算法提供者列表
|
||||
*/
|
||||
private static void printProviders() {
|
||||
log.info("Providers List:");
|
||||
Provider[] providers = Security.getProviders();
|
||||
for (int i = 0; i < providers.length; i++) {
|
||||
log.info(i + 1 + "." + providers[i].getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 证书文件过滤器
|
||||
*
|
||||
*/
|
||||
static class CerFilter implements FilenameFilter {
|
||||
public boolean isCer(String name) {
|
||||
if (name.toLowerCase().endsWith(".cer")) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return isCer(name);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,690 @@
|
||||
package com.egzosn.pay.union.SDK;
|
||||
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
*
|
||||
* @ClassName SDKConfig
|
||||
* @Description acpsdk配置文件acp_sdk.properties配置信息类
|
||||
* @date 2016-7-22 下午4:04:55
|
||||
* @lastUpdate Actinia Date:2017/11/7 0007 21:55
|
||||
*
|
||||
*/
|
||||
public class SDKConfig {
|
||||
protected final Log log = LogFactory.getLog(SDKConfig.class);
|
||||
|
||||
public static final String FILE_NAME = "acp_sdk.properties";
|
||||
/** 前台请求URL. */
|
||||
private String frontRequestUrl;
|
||||
/** 后台请求URL. */
|
||||
private String backRequestUrl;
|
||||
/** 单笔查询 */
|
||||
private String singleQueryUrl;
|
||||
/** 批量查询 */
|
||||
private String batchQueryUrl;
|
||||
/** 批量交易 */
|
||||
private String batchTransUrl;
|
||||
/** 文件传输 */
|
||||
private String fileTransUrl;
|
||||
/** 签名证书路径. */
|
||||
private String signCertPath;
|
||||
/** 签名证书密码. */
|
||||
private String signCertPwd;
|
||||
/** 签名证书类型. */
|
||||
private String signCertType;
|
||||
/** 加密公钥证书路径. */
|
||||
private String encryptCertPath;
|
||||
/** 验证签名公钥证书目录. */
|
||||
private String validateCertDir;
|
||||
/** 按照商户代码读取指定签名证书目录. */
|
||||
private String signCertDir;
|
||||
/** 磁道加密证书路径. */
|
||||
private String encryptTrackCertPath;
|
||||
/** 磁道加密公钥模数. */
|
||||
private String encryptTrackKeyModulus;
|
||||
/** 磁道加密公钥指数. */
|
||||
private String encryptTrackKeyExponent;
|
||||
/** 有卡交易. */
|
||||
private String cardRequestUrl;
|
||||
/** app交易 */
|
||||
private String appRequestUrl;
|
||||
/** 证书使用模式(单证书/多证书) */
|
||||
private String singleMode;
|
||||
/** 安全密钥(SHA256和SM3计算时使用) */
|
||||
private String secureKey;
|
||||
/** 中级证书路径 */
|
||||
private String middleCertPath;
|
||||
/** 根证书路径 */
|
||||
private String rootCertPath;
|
||||
/** 是否验证验签证书CN,除了false都验 */
|
||||
private boolean ifValidateCNName = true;
|
||||
/** 是否验证https证书,默认都不验 */
|
||||
private boolean ifValidateRemoteCert = false;
|
||||
/** signMethod,没配按01吧 */
|
||||
private String signMethod = "01";
|
||||
/** version,没配按5.0.0 */
|
||||
private String version = "5.0.0";
|
||||
/** frontUrl */
|
||||
private String frontUrl;
|
||||
/** backUrl */
|
||||
private String backUrl;
|
||||
|
||||
/*缴费相关地址*/
|
||||
private String jfFrontRequestUrl;
|
||||
private String jfBackRequestUrl;
|
||||
private String jfSingleQueryUrl;
|
||||
private String jfCardRequestUrl;
|
||||
private String jfAppRequestUrl;
|
||||
|
||||
private String qrcBackTransUrl;
|
||||
private String qrcB2cIssBackTransUrl;
|
||||
private String qrcB2cMerBackTransUrl;
|
||||
|
||||
/** 配置文件中的前台URL常量. */
|
||||
public static final String SDK_FRONT_URL = "acpsdk.frontTransUrl";
|
||||
/** 配置文件中的后台URL常量. */
|
||||
public static final String SDK_BACK_URL = "acpsdk.backTransUrl";
|
||||
/** 配置文件中的单笔交易查询URL常量. */
|
||||
public static final String SDK_SIGNQ_URL = "acpsdk.singleQueryUrl";
|
||||
/** 配置文件中的批量交易查询URL常量. */
|
||||
public static final String SDK_BATQ_URL = "acpsdk.batchQueryUrl";
|
||||
/** 配置文件中的批量交易URL常量. */
|
||||
public static final String SDK_BATTRANS_URL = "acpsdk.batchTransUrl";
|
||||
/** 配置文件中的文件类交易URL常量. */
|
||||
public static final String SDK_FILETRANS_URL = "acpsdk.fileTransUrl";
|
||||
/** 配置文件中的有卡交易URL常量. */
|
||||
public static final String SDK_CARD_URL = "acpsdk.cardTransUrl";
|
||||
/** 配置文件中的app交易URL常量. */
|
||||
public static final String SDK_APP_URL = "acpsdk.appTransUrl";
|
||||
|
||||
/** 以下缴费产品使用,其余产品用不到,无视即可 */
|
||||
// 前台请求地址
|
||||
public static final String JF_SDK_FRONT_TRANS_URL= "acpsdk.jfFrontTransUrl";
|
||||
// 后台请求地址
|
||||
public static final String JF_SDK_BACK_TRANS_URL="acpsdk.jfBackTransUrl";
|
||||
// 单笔查询请求地址
|
||||
public static final String JF_SDK_SINGLE_QUERY_URL="acpsdk.jfSingleQueryUrl";
|
||||
// 有卡交易地址
|
||||
public static final String JF_SDK_CARD_TRANS_URL="acpsdk.jfCardTransUrl";
|
||||
// App交易地址
|
||||
public static final String JF_SDK_APP_TRANS_URL="acpsdk.jfAppTransUrl";
|
||||
// 人到人
|
||||
public static final String QRC_BACK_TRANS_URL="acpsdk.qrcBackTransUrl";
|
||||
// 人到人
|
||||
public static final String QRC_B2C_ISS_BACK_TRANS_URL="acpsdk.qrcB2cIssBackTransUrl";
|
||||
// 人到人
|
||||
public static final String QRC_B2C_MER_BACK_TRANS_URL="acpsdk.qrcB2cMerBackTransUrl";
|
||||
|
||||
|
||||
/** 配置文件中签名证书路径常量. */
|
||||
public static final String SDK_SIGNCERT_PATH = "acpsdk.signCert.path";
|
||||
/** 配置文件中签名证书密码常量. */
|
||||
public static final String SDK_SIGNCERT_PWD = "acpsdk.signCert.pwd";
|
||||
/** 配置文件中签名证书类型常量. */
|
||||
public static final String SDK_SIGNCERT_TYPE = "acpsdk.signCert.type";
|
||||
/** 配置文件中密码加密证书路径常量. */
|
||||
public static final String SDK_ENCRYPTCERT_PATH = "acpsdk.encryptCert.path";
|
||||
/** 配置文件中磁道加密证书路径常量. */
|
||||
public static final String SDK_ENCRYPTTRACKCERT_PATH = "acpsdk.encryptTrackCert.path";
|
||||
/** 配置文件中磁道加密公钥模数常量. */
|
||||
public static final String SDK_ENCRYPTTRACKKEY_MODULUS = "acpsdk.encryptTrackKey.modulus";
|
||||
/** 配置文件中磁道加密公钥指数常量. */
|
||||
public static final String SDK_ENCRYPTTRACKKEY_EXPONENT = "acpsdk.encryptTrackKey.exponent";
|
||||
/** 配置文件中验证签名证书目录常量. */
|
||||
public static final String SDK_VALIDATECERT_DIR = "acpsdk.validateCert.dir";
|
||||
|
||||
/** 配置文件中是否加密cvn2常量. */
|
||||
public static final String SDK_CVN_ENC = "acpsdk.cvn2.enc";
|
||||
/** 配置文件中是否加密cvn2有效期常量. */
|
||||
public static final String SDK_DATE_ENC = "acpsdk.date.enc";
|
||||
/** 配置文件中是否加密卡号常量. */
|
||||
public static final String SDK_PAN_ENC = "acpsdk.pan.enc";
|
||||
/** 配置文件中证书使用模式 */
|
||||
public static final String SDK_SINGLEMODE = "acpsdk.singleMode";
|
||||
/** 配置文件中安全密钥 */
|
||||
public static final String SDK_SECURITYKEY = "acpsdk.secureKey";
|
||||
/** 配置文件中根证书路径常量 */
|
||||
public static final String SDK_ROOTCERT_PATH = "acpsdk.rootCert.path";
|
||||
/** 配置文件中根证书路径常量 */
|
||||
public static final String SDK_MIDDLECERT_PATH = "acpsdk.middleCert.path";
|
||||
/** 配置是否需要验证验签证书CN,除了false之外的值都当true处理 */
|
||||
public static final String SDK_IF_VALIDATE_CN_NAME = "acpsdk.ifValidateCNName";
|
||||
/** 配置是否需要验证https证书,除了true之外的值都当false处理 */
|
||||
public static final String SDK_IF_VALIDATE_REMOTE_CERT = "acpsdk.ifValidateRemoteCert";
|
||||
/** signmethod */
|
||||
public static final String SDK_SIGN_METHOD ="acpsdk.signMethod";
|
||||
/** version */
|
||||
public static final String SDK_VERSION = "acpsdk.version";
|
||||
/** 后台通知地址 */
|
||||
public static final String SDK_BACKURL = "acpsdk.backUrl";
|
||||
/** 前台通知地址 */
|
||||
public static final String SDK_FRONTURL = "acpsdk.frontUrl";
|
||||
/** 操作对象. */
|
||||
private static SDKConfig config = new SDKConfig();
|
||||
/** 属性文件对象. */
|
||||
private Properties properties;
|
||||
|
||||
|
||||
private SDKConfig () {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取config对象.
|
||||
* @return
|
||||
*/
|
||||
public static SDKConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从classpath路径下加载配置参数
|
||||
*/
|
||||
public void loadPropertiesFromSrc() {
|
||||
InputStream in = null;
|
||||
try {
|
||||
log.info("从classpath: " +SDKConfig.class.getClassLoader().getResource("").getPath()+" 获取属性文件"+FILE_NAME);
|
||||
in = SDKConfig.class.getClassLoader().getResourceAsStream(FILE_NAME);
|
||||
if (null != in) {
|
||||
properties = new Properties();
|
||||
try {
|
||||
properties.load(in);
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
} else {
|
||||
log.info(FILE_NAME + "属性文件未能在classpath指定的目录下 "+SDKConfig.class.getClassLoader().getResource("").getPath()+" 找到!");
|
||||
return;
|
||||
}
|
||||
loadProperties(properties);
|
||||
} catch (IOException e) {
|
||||
log.info(e.getMessage(), e);
|
||||
} finally {
|
||||
if (null != in) {
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
log.info(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据传入的 {@link #load(java.util.Properties)}对象设置配置参数
|
||||
*
|
||||
* @param pro
|
||||
*/
|
||||
public void loadProperties(Properties pro) {
|
||||
log.info("开始从属性文件中加载配置项");
|
||||
String value = null;
|
||||
|
||||
value = pro.getProperty(SDK_SIGNCERT_PATH);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.signCertPath = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_SIGNCERT_PWD);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.signCertPwd = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_SIGNCERT_TYPE);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.signCertType = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_ENCRYPTCERT_PATH);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.encryptCertPath = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_VALIDATECERT_DIR);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.validateCertDir = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_FRONT_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.frontRequestUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_BACK_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.backRequestUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_BATQ_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.batchQueryUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_BATTRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.batchTransUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_FILETRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.fileTransUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_SIGNQ_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.singleQueryUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_CARD_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.cardRequestUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_APP_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.appRequestUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_ENCRYPTTRACKCERT_PATH);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.encryptTrackCertPath = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(SDK_SECURITYKEY);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.secureKey = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_ROOTCERT_PATH);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.rootCertPath = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_MIDDLECERT_PATH);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.middleCertPath = value.trim();
|
||||
}
|
||||
|
||||
/**缴费部分**/
|
||||
value = pro.getProperty(JF_SDK_FRONT_TRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.jfFrontRequestUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(JF_SDK_BACK_TRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.jfBackRequestUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(JF_SDK_SINGLE_QUERY_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.jfSingleQueryUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(JF_SDK_CARD_TRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.jfCardRequestUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(JF_SDK_APP_TRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.jfAppRequestUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(QRC_BACK_TRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.qrcBackTransUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(QRC_B2C_ISS_BACK_TRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.qrcB2cIssBackTransUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(QRC_B2C_MER_BACK_TRANS_URL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.qrcB2cMerBackTransUrl = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(SDK_ENCRYPTTRACKKEY_EXPONENT);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.encryptTrackKeyExponent = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(SDK_ENCRYPTTRACKKEY_MODULUS);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.encryptTrackKeyModulus = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(SDK_IF_VALIDATE_CN_NAME);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
if( "false".equals(value.trim())) {
|
||||
this.ifValidateCNName = false;
|
||||
}
|
||||
}
|
||||
|
||||
value = pro.getProperty(SDK_IF_VALIDATE_REMOTE_CERT);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
if( "true".equals(value.trim())) {
|
||||
this.ifValidateRemoteCert = true;
|
||||
}
|
||||
}
|
||||
|
||||
value = pro.getProperty(SDK_SIGN_METHOD);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.signMethod = value.trim();
|
||||
}
|
||||
|
||||
value = pro.getProperty(SDK_SIGN_METHOD);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.signMethod = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_VERSION);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.version = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_FRONTURL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.frontUrl = value.trim();
|
||||
}
|
||||
value = pro.getProperty(SDK_BACKURL);
|
||||
if (!StringUtils.isEmpty(value)) {
|
||||
this.backUrl = value.trim();
|
||||
}
|
||||
}
|
||||
|
||||
public String getSignMethod () {
|
||||
return signMethod;
|
||||
}
|
||||
|
||||
public void setSignMethod (String signMethod) {
|
||||
this.signMethod = signMethod;
|
||||
}
|
||||
|
||||
public String getSignMethodByStr(String signStr) {
|
||||
if(StringUtils.isBlank(signStr)){
|
||||
return SDKConstants.SIGNMETHOD_RSA;
|
||||
}
|
||||
signStr = signStr.toUpperCase();
|
||||
switch (signStr) {
|
||||
case "RSA":
|
||||
return SDKConstants.SIGNMETHOD_RSA;
|
||||
case "SHA256":
|
||||
return SDKConstants.SIGNMETHOD_SHA256;
|
||||
case "SM3":
|
||||
return SDKConstants.SIGNMETHOD_SM3;
|
||||
default:
|
||||
return SDKConstants.SIGNMETHOD_RSA;
|
||||
}
|
||||
}
|
||||
|
||||
public String getFrontRequestUrl() {
|
||||
return frontRequestUrl;
|
||||
}
|
||||
|
||||
public void setFrontRequestUrl(String frontRequestUrl) {
|
||||
this.frontRequestUrl = frontRequestUrl;
|
||||
}
|
||||
|
||||
public String getBackRequestUrl() {
|
||||
return backRequestUrl;
|
||||
}
|
||||
|
||||
public void setBackRequestUrl(String backRequestUrl) {
|
||||
this.backRequestUrl = backRequestUrl;
|
||||
}
|
||||
|
||||
public String getSignCertPath() {
|
||||
return signCertPath;
|
||||
}
|
||||
|
||||
public void setSignCertPath(String signCertPath) {
|
||||
this.signCertPath = signCertPath;
|
||||
}
|
||||
|
||||
public String getSignCertPwd() {
|
||||
return signCertPwd;
|
||||
}
|
||||
|
||||
public void setSignCertPwd(String signCertPwd) {
|
||||
this.signCertPwd = signCertPwd;
|
||||
}
|
||||
|
||||
public String getSignCertType() {
|
||||
return signCertType;
|
||||
}
|
||||
|
||||
public void setSignCertType(String signCertType) {
|
||||
this.signCertType = signCertType;
|
||||
}
|
||||
|
||||
public String getEncryptCertPath() {
|
||||
return encryptCertPath;
|
||||
}
|
||||
|
||||
public void setEncryptCertPath(String encryptCertPath) {
|
||||
this.encryptCertPath = encryptCertPath;
|
||||
}
|
||||
|
||||
public String getValidateCertDir() {
|
||||
return validateCertDir;
|
||||
}
|
||||
|
||||
public void setValidateCertDir(String validateCertDir) {
|
||||
this.validateCertDir = validateCertDir;
|
||||
}
|
||||
|
||||
public String getSingleQueryUrl() {
|
||||
return singleQueryUrl;
|
||||
}
|
||||
|
||||
public void setSingleQueryUrl(String singleQueryUrl) {
|
||||
this.singleQueryUrl = singleQueryUrl;
|
||||
}
|
||||
|
||||
public String getBatchQueryUrl() {
|
||||
return batchQueryUrl;
|
||||
}
|
||||
|
||||
public void setBatchQueryUrl(String batchQueryUrl) {
|
||||
this.batchQueryUrl = batchQueryUrl;
|
||||
}
|
||||
|
||||
public String getBatchTransUrl() {
|
||||
return batchTransUrl;
|
||||
}
|
||||
|
||||
public void setBatchTransUrl(String batchTransUrl) {
|
||||
this.batchTransUrl = batchTransUrl;
|
||||
}
|
||||
|
||||
public String getFileTransUrl() {
|
||||
return fileTransUrl;
|
||||
}
|
||||
|
||||
public void setFileTransUrl(String fileTransUrl) {
|
||||
this.fileTransUrl = fileTransUrl;
|
||||
}
|
||||
|
||||
public String getSignCertDir() {
|
||||
return signCertDir;
|
||||
}
|
||||
|
||||
public void setSignCertDir(String signCertDir) {
|
||||
this.signCertDir = signCertDir;
|
||||
}
|
||||
|
||||
public Properties getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
public String getCardRequestUrl() {
|
||||
return cardRequestUrl;
|
||||
}
|
||||
|
||||
public void setCardRequestUrl(String cardRequestUrl) {
|
||||
this.cardRequestUrl = cardRequestUrl;
|
||||
}
|
||||
|
||||
public String getAppRequestUrl() {
|
||||
return appRequestUrl;
|
||||
}
|
||||
|
||||
public void setAppRequestUrl(String appRequestUrl) {
|
||||
this.appRequestUrl = appRequestUrl;
|
||||
}
|
||||
|
||||
public String getEncryptTrackCertPath() {
|
||||
return encryptTrackCertPath;
|
||||
}
|
||||
|
||||
public void setEncryptTrackCertPath(String encryptTrackCertPath) {
|
||||
this.encryptTrackCertPath = encryptTrackCertPath;
|
||||
}
|
||||
|
||||
public String getJfFrontRequestUrl() {
|
||||
return jfFrontRequestUrl;
|
||||
}
|
||||
|
||||
public void setJfFrontRequestUrl(String jfFrontRequestUrl) {
|
||||
this.jfFrontRequestUrl = jfFrontRequestUrl;
|
||||
}
|
||||
|
||||
public String getJfBackRequestUrl() {
|
||||
return jfBackRequestUrl;
|
||||
}
|
||||
|
||||
public void setJfBackRequestUrl(String jfBackRequestUrl) {
|
||||
this.jfBackRequestUrl = jfBackRequestUrl;
|
||||
}
|
||||
|
||||
public String getJfSingleQueryUrl() {
|
||||
return jfSingleQueryUrl;
|
||||
}
|
||||
|
||||
public void setJfSingleQueryUrl(String jfSingleQueryUrl) {
|
||||
this.jfSingleQueryUrl = jfSingleQueryUrl;
|
||||
}
|
||||
|
||||
public String getJfCardRequestUrl() {
|
||||
return jfCardRequestUrl;
|
||||
}
|
||||
|
||||
public void setJfCardRequestUrl(String jfCardRequestUrl) {
|
||||
this.jfCardRequestUrl = jfCardRequestUrl;
|
||||
}
|
||||
|
||||
public String getJfAppRequestUrl() {
|
||||
return jfAppRequestUrl;
|
||||
}
|
||||
|
||||
public void setJfAppRequestUrl(String jfAppRequestUrl) {
|
||||
this.jfAppRequestUrl = jfAppRequestUrl;
|
||||
}
|
||||
|
||||
public String getSingleMode() {
|
||||
return singleMode;
|
||||
}
|
||||
|
||||
public void setSingleMode(String singleMode) {
|
||||
this.singleMode = singleMode;
|
||||
}
|
||||
|
||||
public String getEncryptTrackKeyExponent() {
|
||||
return encryptTrackKeyExponent;
|
||||
}
|
||||
|
||||
public void setEncryptTrackKeyExponent(String encryptTrackKeyExponent) {
|
||||
this.encryptTrackKeyExponent = encryptTrackKeyExponent;
|
||||
}
|
||||
|
||||
public String getEncryptTrackKeyModulus() {
|
||||
return encryptTrackKeyModulus;
|
||||
}
|
||||
|
||||
public void setEncryptTrackKeyModulus(String encryptTrackKeyModulus) {
|
||||
this.encryptTrackKeyModulus = encryptTrackKeyModulus;
|
||||
}
|
||||
|
||||
public String getSecureKey() {
|
||||
return secureKey;
|
||||
}
|
||||
|
||||
public void setSecureKey(String securityKey) {
|
||||
this.secureKey = securityKey;
|
||||
}
|
||||
|
||||
public String getMiddleCertPath() {
|
||||
return middleCertPath;
|
||||
}
|
||||
|
||||
public void setMiddleCertPath(String middleCertPath) {
|
||||
this.middleCertPath = middleCertPath;
|
||||
}
|
||||
|
||||
public boolean isIfValidateCNName() {
|
||||
return ifValidateCNName;
|
||||
}
|
||||
|
||||
public void setIfValidateCNName(boolean ifValidateCNName) {
|
||||
this.ifValidateCNName = ifValidateCNName;
|
||||
}
|
||||
|
||||
public boolean isIfValidateRemoteCert() {
|
||||
return ifValidateRemoteCert;
|
||||
}
|
||||
|
||||
public void setIfValidateRemoteCert(boolean ifValidateRemoteCert) {
|
||||
this.ifValidateRemoteCert = ifValidateRemoteCert;
|
||||
}
|
||||
|
||||
public String getQrcBackTransUrl() {
|
||||
return qrcBackTransUrl;
|
||||
}
|
||||
|
||||
public void setQrcBackTransUrl(String qrcBackTransUrl) {
|
||||
this.qrcBackTransUrl = qrcBackTransUrl;
|
||||
}
|
||||
|
||||
public String getQrcB2cIssBackTransUrl() {
|
||||
return qrcB2cIssBackTransUrl;
|
||||
}
|
||||
|
||||
public void setQrcB2cIssBackTransUrl(String qrcB2cIssBackTransUrl) {
|
||||
this.qrcB2cIssBackTransUrl = qrcB2cIssBackTransUrl;
|
||||
}
|
||||
|
||||
public String getQrcB2cMerBackTransUrl() {
|
||||
return qrcB2cMerBackTransUrl;
|
||||
}
|
||||
|
||||
public void setQrcB2cMerBackTransUrl(String qrcB2cMerBackTransUrl) {
|
||||
this.qrcB2cMerBackTransUrl = qrcB2cMerBackTransUrl;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String getFrontUrl() {
|
||||
return frontUrl;
|
||||
}
|
||||
|
||||
public void setFrontUrl(String frontUrl) {
|
||||
this.frontUrl = frontUrl;
|
||||
}
|
||||
|
||||
public String getBackUrl() {
|
||||
return backUrl;
|
||||
}
|
||||
|
||||
public void setBackUrl(String backUrl) {
|
||||
this.backUrl = backUrl;
|
||||
}
|
||||
|
||||
public String getRootCertPath() {
|
||||
return rootCertPath;
|
||||
}
|
||||
|
||||
public void setRootCertPath(String rootCertPath) {
|
||||
this.rootCertPath = rootCertPath;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
/**
|
||||
* Licensed Property to China UnionPay Co., Ltd.
|
||||
* <p>
|
||||
* (C) Copyright of China UnionPay Co., Ltd. 2010
|
||||
* All Rights Reserved.
|
||||
* <p>
|
||||
* <p>
|
||||
* Modification History:
|
||||
* =============================================================================
|
||||
* Author Date Description
|
||||
* ------------ ---------- ---------------------------------------------------
|
||||
* xshu 2014-05-28 MPI插件包常量定义
|
||||
* =============================================================================
|
||||
*/
|
||||
package com.egzosn.pay.union.SDK;
|
||||
|
||||
/**
|
||||
*
|
||||
* @ClassName SDKConstants
|
||||
* @Description acpsdk常量类
|
||||
* @date 2016-7-22 下午4:05:54
|
||||
*
|
||||
*/
|
||||
public class SDKConstants {
|
||||
|
||||
public final static String COLUMN_DEFAULT = "-";
|
||||
|
||||
public final static String KEY_DELIMITER = "#";
|
||||
|
||||
/** memeber variable: blank. */
|
||||
public static final String BLANK = "";
|
||||
|
||||
/** member variabel: space. */
|
||||
public static final String SPACE = " ";
|
||||
|
||||
/** memeber variable: unline. */
|
||||
public static final String UNLINE = "_";
|
||||
|
||||
/** memeber varibale: star. */
|
||||
public static final String STAR = "*";
|
||||
|
||||
/** memeber variable: line. */
|
||||
public static final String LINE = "-";
|
||||
|
||||
/** memeber variable: add. */
|
||||
public static final String ADD = "+";
|
||||
|
||||
/** memeber variable: colon. */
|
||||
public final static String COLON = "|";
|
||||
|
||||
/** memeber variable: point. */
|
||||
public final static String POINT = ".";
|
||||
|
||||
/** memeber variable: comma. */
|
||||
public final static String COMMA = ",";
|
||||
|
||||
/** memeber variable: slash. */
|
||||
public final static String SLASH = "/";
|
||||
|
||||
/** memeber variable: div. */
|
||||
public final static String DIV = "/";
|
||||
|
||||
/** memeber variable: left . */
|
||||
public final static String LB = "(";
|
||||
|
||||
/** memeber variable: right. */
|
||||
public final static String RB = ")";
|
||||
|
||||
/** memeber variable: rmb. */
|
||||
public final static String CUR_RMB = "RMB";
|
||||
|
||||
/** memeber variable: .page size */
|
||||
public static final int PAGE_SIZE = 10;
|
||||
|
||||
/** memeber variable: String ONE. */
|
||||
public static final String ONE = "1";
|
||||
|
||||
/** memeber variable: String ZERO. */
|
||||
public static final String ZERO = "0";
|
||||
|
||||
/** memeber variable: number six. */
|
||||
public static final int NUM_SIX = 6;
|
||||
|
||||
/** memeber variable: equal mark. */
|
||||
public static final String EQUAL = "=";
|
||||
|
||||
/** memeber variable: operation ne. */
|
||||
public static final String NE = "!=";
|
||||
|
||||
/** memeber variable: operation le. */
|
||||
public static final String LE = "<=";
|
||||
|
||||
/** memeber variable: operation ge. */
|
||||
public static final String GE = ">=";
|
||||
|
||||
/** memeber variable: operation lt. */
|
||||
public static final String LT = "<";
|
||||
|
||||
/** memeber variable: operation gt. */
|
||||
public static final String GT = ">";
|
||||
|
||||
/** memeber variable: list separator. */
|
||||
public static final String SEP = "./";
|
||||
|
||||
/** memeber variable: Y. */
|
||||
public static final String Y = "Y";
|
||||
|
||||
/** memeber variable: AMPERSAND. */
|
||||
public static final String AMPERSAND = "&";
|
||||
|
||||
/** memeber variable: SQL_LIKE_TAG. */
|
||||
public static final String SQL_LIKE_TAG = "%";
|
||||
|
||||
/** memeber variable: @. */
|
||||
public static final String MAIL = "@";
|
||||
|
||||
/** memeber variable: number zero. */
|
||||
public static final int NZERO = 0;
|
||||
|
||||
public static final String LEFT_BRACE = "{";
|
||||
|
||||
public static final String RIGHT_BRACE = "}";
|
||||
|
||||
/** memeber variable: string true. */
|
||||
public static final String TRUE_STRING = "true";
|
||||
/** memeber variable: string false. */
|
||||
public static final String FALSE_STRING = "false";
|
||||
|
||||
/** memeber variable: forward success. */
|
||||
public static final String SUCCESS = "success";
|
||||
/** memeber variable: forward fail. */
|
||||
public static final String FAIL = "fail";
|
||||
/** memeber variable: global forward success. */
|
||||
public static final String GLOBAL_SUCCESS = "$success";
|
||||
/** memeber variable: global forward fail. */
|
||||
public static final String GLOBAL_FAIL = "$fail";
|
||||
|
||||
public static final String UTF_8_ENCODING = "UTF-8";
|
||||
public static final String GBK_ENCODING = "GBK";
|
||||
public static final String CONTENT_TYPE = "Content-type";
|
||||
public static final String APP_XML_TYPE = "application/xml;charset=utf-8";
|
||||
public static final String APP_FORM_TYPE = "application/x-www-form-urlencoded;charset=";
|
||||
|
||||
public static final String VERSION_1_0_0 = "1.0.0";
|
||||
public static final String VERSION_5_0_0 = "5.0.0";
|
||||
public static final String VERSION_5_0_1 = "5.0.1";
|
||||
public static final String VERSION_5_1_0 = "5.1.0";
|
||||
public static final String SIGNMETHOD_RSA = "01";
|
||||
public static final String SIGNMETHOD_SHA256 = "11";
|
||||
public static final String SIGNMETHOD_SM3 = "12";
|
||||
public static final String UNIONPAY_CNNAME = "中国银联股份有限公司";
|
||||
public static final String CERTTYPE_01 = "01";// 敏感信息加密公钥
|
||||
public static final String CERTTYPE_02 = "02";// 磁道加密公钥
|
||||
|
||||
/******************************************** 5.0报文接口定义 ********************************************/
|
||||
/** 版本号. */
|
||||
public static final String param_version = "version";
|
||||
/** 证书ID. */
|
||||
public static final String param_certId = "certId";
|
||||
/** 签名. */
|
||||
public static final String param_signature = "signature";
|
||||
/** 签名方法. */
|
||||
public static final String param_signMethod = "signMethod";
|
||||
/** 编码方式. */
|
||||
public static final String param_encoding = "encoding";
|
||||
/** 交易类型. */
|
||||
public static final String param_txnType = "txnType";
|
||||
/** 交易子类. */
|
||||
public static final String param_txnSubType = "txnSubType";
|
||||
/** 业务类型. */
|
||||
public static final String param_bizType = "bizType";
|
||||
/** 前台通知地址 . */
|
||||
public static final String param_frontUrl = "frontUrl";
|
||||
/** 后台通知地址. */
|
||||
public static final String param_backUrl = "backUrl";
|
||||
/** 接入类型. */
|
||||
public static final String param_accessType = "accessType";
|
||||
/** 收单机构代码. */
|
||||
public static final String param_acqInsCode = "acqInsCode";
|
||||
/** 商户类别. */
|
||||
public static final String param_merCatCode = "merCatCode";
|
||||
/** 商户类型. */
|
||||
public static final String param_merType = "merType";
|
||||
/** 商户代码. */
|
||||
public static final String param_merId = "merId";
|
||||
/** 商户名称. */
|
||||
public static final String param_merName = "merName";
|
||||
/** 商户简称. */
|
||||
public static final String param_merAbbr = "merAbbr";
|
||||
/** 二级商户代码. */
|
||||
public static final String param_subMerId = "subMerId";
|
||||
/** 二级商户名称. */
|
||||
public static final String param_subMerName = "subMerName";
|
||||
/** 二级商户简称. */
|
||||
public static final String param_subMerAbbr = "subMerAbbr";
|
||||
/** Cupsecure 商户代码. */
|
||||
public static final String param_csMerId = "csMerId";
|
||||
/** 商户订单号. */
|
||||
public static final String param_orderId = "orderId";
|
||||
/** 交易时间. */
|
||||
public static final String param_txnTime = "txnTime";
|
||||
/** 发送时间. */
|
||||
public static final String param_txnSendTime = "txnSendTime";
|
||||
/** 订单超时时间间隔. */
|
||||
public static final String param_orderTimeoutInterval = "orderTimeoutInterval";
|
||||
/** 支付超时时间. */
|
||||
public static final String param_payTimeoutTime = "payTimeoutTime";
|
||||
/** 默认支付方式. */
|
||||
public static final String param_defaultPayType = "defaultPayType";
|
||||
/** 支持支付方式. */
|
||||
public static final String param_supPayType = "supPayType";
|
||||
/** 支付方式. */
|
||||
public static final String param_payType = "payType";
|
||||
/** 自定义支付方式. */
|
||||
public static final String param_customPayType = "customPayType";
|
||||
/** 物流标识. */
|
||||
public static final String param_shippingFlag = "shippingFlag";
|
||||
/** 收货地址-国家. */
|
||||
public static final String param_shippingCountryCode = "shippingCountryCode";
|
||||
/** 收货地址-省. */
|
||||
public static final String param_shippingProvinceCode = "shippingProvinceCode";
|
||||
/** 收货地址-市. */
|
||||
public static final String param_shippingCityCode = "shippingCityCode";
|
||||
/** 收货地址-地区. */
|
||||
public static final String param_shippingDistrictCode = "shippingDistrictCode";
|
||||
/** 收货地址-详细. */
|
||||
public static final String param_shippingStreet = "shippingStreet";
|
||||
/** 商品总类. */
|
||||
public static final String param_commodityCategory = "commodityCategory";
|
||||
/** 商品名称. */
|
||||
public static final String param_commodityName = "commodityName";
|
||||
/** 商品URL. */
|
||||
public static final String param_commodityUrl = "commodityUrl";
|
||||
/** 商品单价. */
|
||||
public static final String param_commodityUnitPrice = "commodityUnitPrice";
|
||||
/** 商品数量. */
|
||||
public static final String param_commodityQty = "commodityQty";
|
||||
/** 是否预授权. */
|
||||
public static final String param_isPreAuth = "isPreAuth";
|
||||
/** 币种. */
|
||||
public static final String param_currencyCode = "currencyCode";
|
||||
/** 账户类型. */
|
||||
public static final String param_accType = "accType";
|
||||
/** 账号. */
|
||||
public static final String param_accNo = "accNo";
|
||||
/** 支付卡类型. */
|
||||
public static final String param_payCardType = "payCardType";
|
||||
/** 发卡机构代码. */
|
||||
public static final String param_issInsCode = "issInsCode";
|
||||
/** 持卡人信息. */
|
||||
public static final String param_customerInfo = "customerInfo";
|
||||
/** 交易金额. */
|
||||
public static final String param_txnAmt = "txnAmt";
|
||||
/** 余额. */
|
||||
public static final String param_balance = "balance";
|
||||
/** 地区代码. */
|
||||
public static final String param_districtCode = "districtCode";
|
||||
/** 附加地区代码. */
|
||||
public static final String param_additionalDistrictCode = "additionalDistrictCode";
|
||||
/** 账单类型. */
|
||||
public static final String param_billType = "billType";
|
||||
/** 账单号码. */
|
||||
public static final String param_billNo = "billNo";
|
||||
/** 账单月份. */
|
||||
public static final String param_billMonth = "billMonth";
|
||||
/** 账单查询要素. */
|
||||
public static final String param_billQueryInfo = "billQueryInfo";
|
||||
/** 账单详情. */
|
||||
public static final String param_billDetailInfo = "billDetailInfo";
|
||||
/** 账单金额. */
|
||||
public static final String param_billAmt = "billAmt";
|
||||
/** 账单金额符号. */
|
||||
public static final String param_billAmtSign = "billAmtSign";
|
||||
/** 绑定标识号. */
|
||||
public static final String param_bindId = "bindId";
|
||||
/** 风险级别. */
|
||||
public static final String param_riskLevel = "riskLevel";
|
||||
/** 绑定信息条数. */
|
||||
public static final String param_bindInfoQty = "bindInfoQty";
|
||||
/** 绑定信息集. */
|
||||
public static final String param_bindInfoList = "bindInfoList";
|
||||
/** 批次号. */
|
||||
public static final String param_batchNo = "batchNo";
|
||||
/** 总笔数. */
|
||||
public static final String param_totalQty = "totalQty";
|
||||
/** 总金额. */
|
||||
public static final String param_totalAmt = "totalAmt";
|
||||
/** 文件类型. */
|
||||
public static final String param_fileType = "fileType";
|
||||
/** 文件名称. */
|
||||
public static final String param_fileName = "fileName";
|
||||
/** 批量文件内容. */
|
||||
public static final String param_fileContent = "fileContent";
|
||||
/** 商户摘要. */
|
||||
public static final String param_merNote = "merNote";
|
||||
/** 商户自定义域. */
|
||||
// public static final String param_merReserved = "merReserved";//接口变更删除
|
||||
/** 请求方保留域. */
|
||||
public static final String param_reqReserved = "reqReserved";// 新增接口
|
||||
/** 保留域. */
|
||||
public static final String param_reserved = "reserved";
|
||||
/** 终端号. */
|
||||
public static final String param_termId = "termId";
|
||||
/** 终端类型. */
|
||||
public static final String param_termType = "termType";
|
||||
/** 交互模式. */
|
||||
public static final String param_interactMode = "interactMode";
|
||||
/** 发卡机构识别模式. */
|
||||
// public static final String param_recognitionMode = "recognitionMode";
|
||||
public static final String param_issuerIdentifyMode = "issuerIdentifyMode";// 接口名称变更
|
||||
/** 商户端用户号. */
|
||||
public static final String param_merUserId = "merUserId";
|
||||
/** 持卡人IP. */
|
||||
public static final String param_customerIp = "customerIp";
|
||||
/** 查询流水号. */
|
||||
public static final String param_queryId = "queryId";
|
||||
/** 原交易查询流水号. */
|
||||
public static final String param_origQryId = "origQryId";
|
||||
/** 系统跟踪号. */
|
||||
public static final String param_traceNo = "traceNo";
|
||||
/** 交易传输时间. */
|
||||
public static final String param_traceTime = "traceTime";
|
||||
/** 清算日期. */
|
||||
public static final String param_settleDate = "settleDate";
|
||||
/** 清算币种. */
|
||||
public static final String param_settleCurrencyCode = "settleCurrencyCode";
|
||||
/** 清算金额. */
|
||||
public static final String param_settleAmt = "settleAmt";
|
||||
/** 清算汇率. */
|
||||
public static final String param_exchangeRate = "exchangeRate";
|
||||
/** 兑换日期. */
|
||||
public static final String param_exchangeDate = "exchangeDate";
|
||||
/** 响应时间. */
|
||||
public static final String param_respTime = "respTime";
|
||||
/** 原交易应答码. */
|
||||
public static final String param_origRespCode = "origRespCode";
|
||||
/** 原交易应答信息. */
|
||||
public static final String param_origRespMsg = "origRespMsg";
|
||||
/** 应答码. */
|
||||
public static final String param_respCode = "respCode";
|
||||
/** 应答码信息. */
|
||||
public static final String param_respMsg = "respMsg";
|
||||
// 新增四个报文字段merUserRegDt merUserEmail checkFlag activateStatus
|
||||
/** 商户端用户注册时间. */
|
||||
public static final String param_merUserRegDt = "merUserRegDt";
|
||||
/** 商户端用户注册邮箱. */
|
||||
public static final String param_merUserEmail = "merUserEmail";
|
||||
/** 验证标识. */
|
||||
public static final String param_checkFlag = "checkFlag";
|
||||
/** 开通状态. */
|
||||
public static final String param_activateStatus = "activateStatus";
|
||||
/** 加密证书ID. */
|
||||
public static final String param_encryptCertId = "encryptCertId";
|
||||
/** 用户MAC、IMEI串号、SSID. */
|
||||
public static final String param_userMac = "userMac";
|
||||
/** 关联交易. */
|
||||
// public static final String param_relationTxnType = "relationTxnType";
|
||||
/** 短信类型 */
|
||||
public static final String param_smsType = "smsType";
|
||||
|
||||
/** 风控信息域 */
|
||||
public static final String param_riskCtrlInfo = "riskCtrlInfo";
|
||||
|
||||
/** IC卡交易信息域 */
|
||||
public static final String param_ICTransData = "ICTransData";
|
||||
|
||||
/** VPC交易信息域 */
|
||||
public static final String param_VPCTransData = "VPCTransData";
|
||||
|
||||
/** 安全类型 */
|
||||
public static final String param_securityType = "securityType";
|
||||
|
||||
/** 银联订单号 */
|
||||
public static final String param_tn = "tn";
|
||||
|
||||
/** 分期付款手续费率 */
|
||||
public static final String param_instalRate = "instalRate";
|
||||
|
||||
/** 分期付款手续费率 */
|
||||
public static final String param_mchntFeeSubsidy = "mchntFeeSubsidy";
|
||||
|
||||
/** 签名公钥证书 */
|
||||
public static final String param_signPubKeyCert = "signPubKeyCert";
|
||||
|
||||
/** 加密公钥证书 */
|
||||
public static final String param_encryptPubKeyCert = "encryptPubKeyCert";
|
||||
|
||||
/** 证书类型 */
|
||||
public static final String param_certType = "certType";
|
||||
|
||||
/** 渠道类型*/
|
||||
public static final String param_channelType = "channelType";
|
||||
|
||||
/** C2B码,1-20位数字*/
|
||||
public static final String param_qrNo = "qrNo";
|
||||
|
||||
/*原交易商户订单号*/
|
||||
public static final String param_origOrderId = "origOrderId";
|
||||
|
||||
/*原交易商户发送交易时间*/
|
||||
public static final String param_origTxnTime = "origTxnTime";
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package com.egzosn.pay.union.SDK;/**
|
||||
* Description:
|
||||
* author: Fuzx
|
||||
* date: 2017/11/27 0027
|
||||
*/
|
||||
|
||||
import com.egzosn.pay.common.util.sign.SecureUtil;
|
||||
import com.egzosn.pay.common.util.sign.SignUtils;
|
||||
import com.egzosn.pay.common.util.sign.encrypt.Base64;
|
||||
import com.egzosn.pay.common.util.sign.encrypt.RSA;
|
||||
import com.egzosn.pay.common.util.sign.encrypt.SHA256;
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.io.*;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.zip.Inflater;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import static com.egzosn.pay.union.SDK.SDKConstants.*;
|
||||
|
||||
/**
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* @create 2017 2017/11/27 0027
|
||||
*/
|
||||
public class SDKUtils {
|
||||
//日志
|
||||
protected static final Log log = LogFactory.getLog(SDKUtils.class);
|
||||
|
||||
/**
|
||||
* 验证签名
|
||||
*
|
||||
* @param resData
|
||||
* 返回报文数据
|
||||
* @param encoding
|
||||
* 编码格式
|
||||
* @return
|
||||
*/
|
||||
public static boolean validate(Map<String, Object> resData, String encoding) {
|
||||
log.info("验签处理开始");
|
||||
if (StringUtils.isEmpty(encoding)) {
|
||||
encoding = "UTF-8";
|
||||
}
|
||||
String signMethod = resData.get(SDKConstants.param_signMethod).toString();
|
||||
String version = resData.get(SDKConstants.param_version).toString();
|
||||
if (SIGNMETHOD_RSA.equals(signMethod) || VERSION_1_0_0.equals(version) || VERSION_5_0_1.equals(version)) {
|
||||
// 获取返回报文的版本号
|
||||
if (VERSION_5_0_0.equals(version) || VERSION_1_0_0.equals(version) || VERSION_5_0_1.equals(version)) {
|
||||
String stringSign = resData.get(SDKConstants.param_signature).toString();
|
||||
log.info("签名原文:["+stringSign+"]");
|
||||
// 从返回报文中获取certId ,然后去证书静态Map中查询对应验签证书对象
|
||||
String certId = resData.get(SDKConstants.param_certId).toString();
|
||||
log.info("对返回报文串验签使用的验签公钥序列号:["+certId+"]");
|
||||
// 将Map信息转换成key1=value1&key2=value2的形式
|
||||
String stringData = SignUtils.parameterText(resData);
|
||||
log.info("待验签返回报文串:["+stringData+"]");
|
||||
try {
|
||||
// 验证签名需要用银联发给商户的公钥证书.
|
||||
return SecureUtil.validateSignBySoft(CertUtil.getValidatePublicKey(certId), Base64.decode(stringSign),
|
||||
SecureUtil.sha1X16(stringData, encoding));
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
} else if (VERSION_5_1_0.equals(version)) {
|
||||
// 1.从返回报文中获取公钥信息转换成公钥对象
|
||||
String strCert = resData.get(SDKConstants.param_signPubKeyCert).toString();
|
||||
log.info("验签公钥证书:["+strCert+"]");
|
||||
X509Certificate x509Cert = CertUtil.genCertificateByStr(strCert);
|
||||
if(x509Cert == null) {
|
||||
log.error("convert signPubKeyCert failed");
|
||||
return false;
|
||||
}
|
||||
// 2.验证证书链
|
||||
if (!CertUtil.verifyCertificate(x509Cert)) {
|
||||
log.error("验证公钥证书失败,证书信息:["+strCert+"]");
|
||||
return false;
|
||||
}
|
||||
|
||||
// 3.验签
|
||||
String stringSign = resData.get(SDKConstants.param_signature).toString();
|
||||
log.info("签名原文:["+stringSign+"]");
|
||||
// 将Map信息转换成key1=value1&key2=value2的形式
|
||||
String stringData = SignUtils.parameterText(resData);
|
||||
log.info("待验签返回报文串:["+stringData+"]");
|
||||
try {
|
||||
// 验证签名需要用银联发给商户的公钥证书.
|
||||
boolean result = SecureUtil.validateSignBySoft256(x509Cert
|
||||
.getPublicKey(), Base64.decode(stringSign
|
||||
), SHA256.sha256X16(
|
||||
stringData, encoding));
|
||||
log.info("验证签名" + (result? "成功":"失败"));
|
||||
return result;
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
log.error(e.getMessage(), e);
|
||||
} catch (Exception e) {
|
||||
log.error(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (SIGNMETHOD_SHA256.equals(signMethod)) {
|
||||
// 1.进行SHA256验证
|
||||
String stringSign = resData.get(SDKConstants.param_signature).toString();
|
||||
log.info("签名原文:["+stringSign+"]");
|
||||
// 将Map信息转换成key1=value1&key2=value2的形式
|
||||
String stringData = SignUtils.parameterText(resData);
|
||||
log.info("待验签返回报文串:["+stringData+"]");
|
||||
String strBeforeSha256 = stringData
|
||||
+ SDKConstants.AMPERSAND
|
||||
+ SecureUtil.sha256X16Str(SDKConfig.getConfig()
|
||||
.getSecureKey(), encoding);
|
||||
String strAfterSha256 = SecureUtil.sha256X16Str(strBeforeSha256,
|
||||
encoding);
|
||||
boolean result = stringSign.equals(strAfterSha256);
|
||||
log.info("验证签名" + (result? "成功":"失败"));
|
||||
return result;
|
||||
} else if (SIGNMETHOD_SM3.equals(signMethod)) {
|
||||
// 1.进行SM3验证
|
||||
String stringSign = resData.get(SDKConstants.param_signature).toString();
|
||||
log.info("签名原文:["+stringSign+"]");
|
||||
// 将Map信息转换成key1=value1&key2=value2的形式
|
||||
String stringData = SignUtils.parameterText(resData);
|
||||
log.info("待验签返回报文串:["+stringData+"]");
|
||||
String strBeforeSM3 = stringData
|
||||
+ SDKConstants.AMPERSAND
|
||||
+ SecureUtil.sm3X16Str(SDKConfig.getConfig()
|
||||
.getSecureKey(), encoding);
|
||||
String strAfterSM3 = SecureUtil
|
||||
.sm3X16Str(strBeforeSM3, encoding);
|
||||
boolean result = stringSign.equals(strAfterSM3);
|
||||
log.info("验证签名" + (result? "成功":"失败"));
|
||||
return result;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对参数加密
|
||||
* @param data
|
||||
* @param encoding
|
||||
* @return
|
||||
*/
|
||||
public static boolean signParams(Map<String, String> data,String encoding){
|
||||
if (StringUtils.isBlank(encoding)) {
|
||||
encoding = "UTF-8";
|
||||
}
|
||||
String signMethod = data.get(SDKConstants.param_signMethod);
|
||||
String version = data.get(SDKConstants.param_version);
|
||||
if(StringUtils.isBlank(signMethod)){
|
||||
log.info("银联签名方式不能为空");
|
||||
return false;
|
||||
}
|
||||
if(StringUtils.isBlank(version)){
|
||||
log.info("版本号不能为空");
|
||||
return false;
|
||||
}
|
||||
if (SIGNMETHOD_RSA.equals(signMethod)|| VERSION_1_0_0.equals(version) || SDKConstants.VERSION_5_0_1.equals(version)) {
|
||||
if (SDKConstants.VERSION_5_0_0.equals(version) || VERSION_1_0_0.equals(version) || SDKConstants.VERSION_5_0_1.equals(version)) {
|
||||
data.put(SDKConstants.param_certId, CertUtil.getSignCertId());
|
||||
String stringData = SignUtils.parameterText(data);
|
||||
String stringSign = null;
|
||||
try {
|
||||
// 通过SHA1进行摘要并转16进制
|
||||
byte[] signDigest = SecureUtil
|
||||
.sha1X16(stringData, encoding);
|
||||
stringSign = RSA.sign(signDigest, CertUtil.getSignCertPrivateKey());
|
||||
// 设置签名域值
|
||||
data.put(SDKConstants.param_signature, stringSign);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}else if (SDKConstants.SIGNMETHOD_SHA256.equals(signMethod)) {
|
||||
String stringData = SignUtils.parameterText(data);
|
||||
String strBeforeSha256 = stringData
|
||||
+ SDKConstants.AMPERSAND
|
||||
+ SecureUtil.sha256X16Str(SDKConfig.getConfig().getSecureKey(), encoding);
|
||||
String strAfterSha256 = SecureUtil.sha256X16Str(strBeforeSha256,
|
||||
encoding);
|
||||
data.put(SDKConstants.param_signature, strAfterSha256);
|
||||
} else if (SDKConstants.SIGNMETHOD_SM3.equals(signMethod)) {
|
||||
String stringData = SignUtils.parameterText(data);
|
||||
String strBeforeSM3 = stringData
|
||||
+ SDKConstants.AMPERSAND
|
||||
+ SecureUtil.sm3X16Str(SDKConfig.getConfig().getSecureKey(), encoding);
|
||||
String strAfterSM3 = SecureUtil.sm3X16Str(strBeforeSM3, encoding);
|
||||
// 设置签名域值
|
||||
data.put(SDKConstants.param_signature, strAfterSM3);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -3,83 +3,88 @@ package com.egzosn.pay.union.api;
|
||||
import com.egzosn.pay.common.api.BasePayConfigStorage;
|
||||
|
||||
/**
|
||||
* 支付客户端配置存储
|
||||
* author egan
|
||||
*
|
||||
* email egzosn@gmail.com
|
||||
* date 2016-5-18 14:09:01
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
create 2017 2017/11/4 0004
|
||||
* </pre>
|
||||
*/
|
||||
public class UnionPayConfigStorage extends BasePayConfigStorage {
|
||||
|
||||
// 商户PID
|
||||
public volatile String merId ;
|
||||
// 商户签约拿到的pid,partner_id的简称,合作伙伴身份等同于 partner
|
||||
public volatile String pid ;
|
||||
//partner_id的简称,合作伙伴身份
|
||||
// public volatile String partner ;
|
||||
/**
|
||||
* 商户号
|
||||
*/
|
||||
public volatile String merId;
|
||||
|
||||
// 商户收款账号
|
||||
public volatile String seller;
|
||||
/**
|
||||
* 商户收款账号
|
||||
*/
|
||||
public volatile String seller;
|
||||
//公钥
|
||||
private volatile String aliPublicKey;
|
||||
//全渠道固定值
|
||||
public static String version = "5.0.0";
|
||||
|
||||
public String getAliPublicKey() {
|
||||
|
||||
|
||||
public String getAliPublicKey () {
|
||||
return aliPublicKey;
|
||||
}
|
||||
|
||||
public void setAliPublicKey(String aliPublicKey) {
|
||||
public void setAliPublicKey (String aliPublicKey) {
|
||||
setKeyPublic(aliPublicKey);
|
||||
this.aliPublicKey = aliPublicKey;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String getAppid() {
|
||||
public String getAppid () {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #getPid()
|
||||
* @return 合作者id
|
||||
* @see #getPid()
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public String getPartner() {
|
||||
return pid;
|
||||
public String getPartner () {
|
||||
return merId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置合作者id
|
||||
* @see #setPid(String)
|
||||
*
|
||||
* @param partner 合作者id
|
||||
* @see #setPid(String)
|
||||
*/
|
||||
@Deprecated
|
||||
public void setPartner(String partner) {
|
||||
this.pid = partner;
|
||||
public void setPartner (String partner) {
|
||||
this.merId = partner;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPid() {
|
||||
return pid;
|
||||
public String getPid () {
|
||||
return merId;
|
||||
}
|
||||
|
||||
public void setPid(String pid) {
|
||||
this.pid = pid;
|
||||
public void setPid (String pid) {
|
||||
this.merId = pid;
|
||||
}
|
||||
|
||||
public String getSeller() {
|
||||
@Override
|
||||
public String getSeller () {
|
||||
return seller;
|
||||
}
|
||||
|
||||
public void setSeller(String seller) {
|
||||
public void setSeller (String seller) {
|
||||
this.seller = seller;
|
||||
}
|
||||
|
||||
public String getMerId () {
|
||||
return merId;
|
||||
}
|
||||
|
||||
|
||||
public void setMerId (String merId) {
|
||||
this.merId = merId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,464 @@
|
||||
package com.egzosn.pay.union.api;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.egzosn.pay.common.api.BasePayService;
|
||||
import com.egzosn.pay.common.api.Callback;
|
||||
import com.egzosn.pay.common.api.PayConfigStorage;
|
||||
import com.egzosn.pay.common.bean.*;
|
||||
import com.egzosn.pay.common.bean.result.PayException;
|
||||
import com.egzosn.pay.common.exception.PayErrorException;
|
||||
import com.egzosn.pay.common.http.HttpConfigStorage;
|
||||
import com.egzosn.pay.common.util.MatrixToImageWriter;
|
||||
import com.egzosn.pay.common.util.str.StringUtils;
|
||||
import com.egzosn.pay.union.SDK.CertUtil;
|
||||
import com.egzosn.pay.union.SDK.SDKConfig;
|
||||
import com.egzosn.pay.union.SDK.SDKConstants;
|
||||
import com.egzosn.pay.union.SDK.SDKUtils;
|
||||
import com.egzosn.pay.union.enums.UnionTransactionType;
|
||||
import com.egzosn.pay.union.request.UnionQueryOrder;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.InputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* @create 2017 2017/11/5 0005
|
||||
*/
|
||||
public class UnionPayService extends BasePayService {
|
||||
//日志
|
||||
protected static final Log log = LogFactory.getLog(UnionPayService.class);
|
||||
|
||||
|
||||
public UnionPayService (PayConfigStorage payConfigStorage) {
|
||||
super(payConfigStorage);
|
||||
}
|
||||
|
||||
public UnionPayService (PayConfigStorage payConfigStorage, HttpConfigStorage configStorage) {
|
||||
super(payConfigStorage, configStorage);
|
||||
SDKConfig.getConfig().loadPropertiesFromSrc();
|
||||
}
|
||||
|
||||
/**
|
||||
* 银联全渠道系统,产品参数,除了encoding自行选择外其他不需修改
|
||||
* @return 返回参数集合
|
||||
*/
|
||||
private Map<String ,String> getCommonParam(){
|
||||
Map<String ,String> params = new HashMap<>();
|
||||
params.put(SDKConstants.param_version, SDKConfig.getConfig().getVersion());
|
||||
params.put(SDKConstants.param_encoding, payConfigStorage.getInputCharset().toUpperCase());
|
||||
params.put(SDKConstants.param_signMethod, SDKConfig.getConfig().getSignMethodByStr(payConfigStorage.getSignType()));
|
||||
params.put(SDKConstants.param_merId, payConfigStorage.getPid());
|
||||
//接入类型,商户接入填0 ,不需修改(0:直连商户, 1: 收单机构 2:平台商户)
|
||||
params.put(SDKConstants.param_accessType, "0");
|
||||
DateFormat df = new SimpleDateFormat("YYYYMMDDhhmmss");
|
||||
params.put(SDKConstants.param_txnTime, df.format(new Date()));
|
||||
params.put(SDKConstants.param_backUrl, SDKConfig.getConfig().getBackUrl());
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 回调校验
|
||||
*
|
||||
* @param result 回调回来的参数集
|
||||
* @return 签名校验 true通过
|
||||
*/
|
||||
@Override
|
||||
public boolean verify (Map<String, Object> result) {
|
||||
if(result != null){
|
||||
if(SDKUtils.validate(result, payConfigStorage.getInputCharset())){
|
||||
String respCode = result.get("respCode").toString();
|
||||
if(("00").equals(respCode)){
|
||||
|
||||
//成功,获取tn号
|
||||
//String tn = resmap.get("tn");
|
||||
//TODO
|
||||
return true;
|
||||
}else{
|
||||
//其他应答码为失败请排查原因或做失败处理
|
||||
//TODO
|
||||
}
|
||||
}else{
|
||||
// 校验失败
|
||||
}
|
||||
}else{
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 签名校验
|
||||
*
|
||||
* @param params 参数集
|
||||
* @param sign 签名
|
||||
* @return 签名校验 true通过
|
||||
*/
|
||||
@Override
|
||||
public boolean signVerify (Map<String, Object> params, String sign) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 支付宝需要,微信是否也需要再次校验来源,进行订单查询
|
||||
* 校验数据来源
|
||||
*
|
||||
* @param id 业务id, 数据的真实性.
|
||||
* @return true通过
|
||||
*/
|
||||
@Override
|
||||
public boolean verifySource (String id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回创建的订单信息
|
||||
*
|
||||
* @param order 支付订单
|
||||
* @return 订单信息
|
||||
* @see PayOrder 支付订单信息
|
||||
*/
|
||||
@Override
|
||||
public Map orderInfo (PayOrder order) {
|
||||
Map<String, String> params = this.getCommonParam();
|
||||
UnionTransactionType type = (UnionTransactionType)order.getTransactionType();
|
||||
type.convertMap(params);
|
||||
switch (type){
|
||||
case APPLY_QR_CODE:
|
||||
params.put(SDKConstants.param_orderId, order.getOutTradeNo());
|
||||
params.put(SDKConstants.param_txnAmt, order.getPrice().toString());
|
||||
params.put(SDKConstants.param_currencyCode, "156");
|
||||
break;
|
||||
case CONSUME:
|
||||
params.put(SDKConstants.param_orderId, order.getOutTradeNo());
|
||||
params.put(SDKConstants.param_txnAmt, order.getPrice().toString());
|
||||
params.put(SDKConstants.param_currencyCode, "156");
|
||||
|
||||
params.put(SDKConstants.param_qrNo, order.getAuthCode());
|
||||
params.put(SDKConstants.param_termId, order.getDeviceInfo());
|
||||
break;
|
||||
default:
|
||||
}
|
||||
|
||||
return params;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取输出二维码,用户返回给支付端,
|
||||
*
|
||||
* @param order 发起支付的订单信息
|
||||
* @return 返回图片信息,支付时需要的
|
||||
*/
|
||||
@Override
|
||||
public BufferedImage genQrPay (PayOrder order) {
|
||||
Map<String ,String > params = orderInfo(order);
|
||||
CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase());
|
||||
JSONObject response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class);
|
||||
if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){
|
||||
if("00".equals(response.getString(SDKConstants.param_respCode))){
|
||||
//成功,获取tn号
|
||||
return MatrixToImageWriter.writeInfoToJpgBuff( response.getString(SDKConstants.param_respCode));
|
||||
}else{
|
||||
throw new PayErrorException(new PayException(response.getString(SDKConstants.param_respCode), response.getString(SDKConstants.param_respMsg), response.toJSONString()));
|
||||
}
|
||||
}else{
|
||||
throw new PayErrorException(new PayException("1000", "验证签名失败", response.toJSONString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷卡付,pos主动扫码付款(条码付)
|
||||
*
|
||||
* @param order 发起支付的订单信息
|
||||
* @return 返回支付结果
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> microPay (PayOrder order) {
|
||||
Map<String ,String > params = orderInfo(order);
|
||||
CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase());
|
||||
return getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 交易查询接口
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @return 返回查询回来的结果集,支付方原值返回
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> query (String tradeNo, String outTradeNo) {
|
||||
Map<String ,String > params = this.getCommonParam();
|
||||
UnionTransactionType.QUERY.convertMap(params);
|
||||
params.put(SDKConstants.param_orderId,outTradeNo);
|
||||
CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase());
|
||||
JSONObject response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class);
|
||||
if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){
|
||||
if("00".equals(response.getString(SDKConstants.param_respCode))){
|
||||
String origRespCode = response.getString(SDKConstants.param_origRespCode);
|
||||
if(("00").equals(origRespCode)){
|
||||
//交易成功,更新商户订单状态
|
||||
//TODO
|
||||
return response;
|
||||
}else{
|
||||
throw new PayErrorException(new PayException(response.getString(SDKConstants.param_respCode), response.getString(SDKConstants.param_respMsg), response.toJSONString()));
|
||||
}
|
||||
}else{
|
||||
throw new PayErrorException(new PayException(response.getString(SDKConstants.param_respCode), response.getString(SDKConstants.param_respMsg), response.toJSONString()));
|
||||
}
|
||||
}else{
|
||||
throw new PayErrorException(new PayException("1000", "验证签名失败", response.toJSONString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 消费撤销/退货接口
|
||||
*
|
||||
* @return 返回支付方申请退款后的结果
|
||||
*/
|
||||
public Map<String, Object> unionRefundOrConsumeUndo (UnionQueryOrder queryOrder,UnionTransactionType type) {
|
||||
Map<String ,String> params = this.getCommonParam();
|
||||
type.convertMap(params);
|
||||
params.put(SDKConstants.param_orderId,queryOrder.getOrderId());
|
||||
params.put(SDKConstants.param_txnAmt,queryOrder.getTxnAmt());
|
||||
if(StringUtils.isNotBlank(queryOrder.getOrigQryId())) {
|
||||
params.put(SDKConstants.param_origQryId, queryOrder.getOrigQryId());
|
||||
}
|
||||
if(StringUtils.isNotBlank(queryOrder.getOrigOrderId())){
|
||||
params.put(SDKConstants.param_origOrderId,queryOrder.getOrigOrderId());
|
||||
}
|
||||
if(StringUtils.isNotBlank(queryOrder.getOrigTxnTime())) {
|
||||
params.put(SDKConstants.param_origTxnTime, queryOrder.getOrigOrderId());
|
||||
}
|
||||
CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase());
|
||||
JSONObject response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,JSONObject.class);
|
||||
if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){
|
||||
if("00".equals(response.getString(SDKConstants.param_respCode))){
|
||||
String origRespCode = response.getString(SDKConstants.param_origRespCode);
|
||||
//交易成功,更新商户订单状态
|
||||
//TODO
|
||||
return response;
|
||||
|
||||
}else{
|
||||
throw new PayErrorException(new PayException(response.getString(SDKConstants.param_respCode), response.getString(SDKConstants.param_respMsg), response.toJSONString()));
|
||||
}
|
||||
}else{
|
||||
throw new PayErrorException(new PayException("1000", "验证签名失败", response.toJSONString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将请求参数或者请求流转化为 Map
|
||||
*
|
||||
* @param parameterMap 请求参数
|
||||
* @param is 请求流
|
||||
* @return 获得回调的请求参数
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> getParameter2Map (Map<String, String[]> parameterMap, InputStream is) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取输出消息,用户返回给支付端
|
||||
*
|
||||
* @param code 状态
|
||||
* @param message 消息
|
||||
* @return 返回输出消息
|
||||
*/
|
||||
@Override
|
||||
public PayOutMessage getPayOutMessage (String code, String message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取成功输出消息,用户返回给支付端
|
||||
* 主要用于拦截器中返回
|
||||
*
|
||||
* @param payMessage 支付回调消息
|
||||
* @return 返回输出消息
|
||||
*/
|
||||
@Override
|
||||
public PayOutMessage successPayOutMessage (PayMessage payMessage) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取输出消息,用户返回给支付端, 针对于web端
|
||||
*
|
||||
* @param orderInfo 发起支付的订单信息
|
||||
* @param method 请求方式 "post" "get",
|
||||
* @return 获取输出消息,用户返回给支付端, 针对于web端
|
||||
* @see MethodType 请求类型
|
||||
*/
|
||||
@Override
|
||||
public String buildRequest (Map<String, Object> orderInfo, MethodType method) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 交易查询接口,带处理器
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @param callback 处理器
|
||||
* @return 返回查询回来的结果集
|
||||
*/
|
||||
@Override
|
||||
public <T> T query (String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 交易关闭接口
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @return 返回支付方交易关闭后的结果
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> close (String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 交易关闭接口
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @param callback 处理器
|
||||
* @return 返回支付方交易关闭后的结果
|
||||
*/
|
||||
@Override
|
||||
public <T> T close (String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款接口
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @param refundAmount 退款金额
|
||||
* @param totalAmount 总金额
|
||||
* @return 返回支付方申请退款后的结果
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> refund (String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 申请退款接口
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @param refundAmount 退款金额
|
||||
* @param totalAmount 总金额
|
||||
* @param callback 处理器
|
||||
* @return 返回支付方申请退款后的结果
|
||||
*/
|
||||
@Override
|
||||
public <T> T refund (String tradeNo, String outTradeNo, BigDecimal refundAmount, BigDecimal totalAmount, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @return 返回支付方查询退款后的结果
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> refundquery (String tradeNo, String outTradeNo) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询退款
|
||||
*
|
||||
* @param tradeNo 支付平台订单号
|
||||
* @param outTradeNo 商户单号
|
||||
* @param callback 处理器
|
||||
* @return 返回支付方查询退款后的结果
|
||||
*/
|
||||
@Override
|
||||
public <T> T refundquery (String tradeNo, String outTradeNo, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单
|
||||
*
|
||||
* @param billDate 账单时间
|
||||
* @param billType 账单类型
|
||||
* @return 返回fileContent 请自行将数据落地
|
||||
*/
|
||||
@Override
|
||||
public Object downloadbill (Date billDate, String billType) {
|
||||
Map<String ,String > params = this.getCommonParam();
|
||||
UnionTransactionType.File_Transfer.convertMap(params);
|
||||
DateFormat df = new SimpleDateFormat("MMDD");
|
||||
params.put(SDKConstants.param_settleDate,df.format(new Date()));
|
||||
params.put(SDKConstants.param_fileType,billType);
|
||||
CertUtil.sign(params,payConfigStorage.getInputCharset().toUpperCase());
|
||||
Map<String ,Object > response = getHttpRequestTemplate().postForObject(SDKConfig.getConfig().getBackRequestUrl(),params,Map.class);
|
||||
if(SDKUtils.validate(response,payConfigStorage.getInputCharset().toUpperCase())){
|
||||
if("00".equals(response.get(SDKConstants.param_respCode))){
|
||||
|
||||
return response.get(SDKConstants.param_fileContent).toString();
|
||||
|
||||
}else{
|
||||
throw new PayErrorException(new PayException(response.get(SDKConstants.param_respCode).toString(), response.get(SDKConstants.param_respMsg).toString(), response.toString()));
|
||||
}
|
||||
}else{
|
||||
throw new PayErrorException(new PayException("1000", "验证签名失败", response.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 下载对账单
|
||||
*
|
||||
* @param billDate 账单时间:具体请查看对应支付平台
|
||||
* @param billType 账单类型,具体请查看对应支付平台
|
||||
* @param callback 处理器
|
||||
* @return 返回支付方下载对账单的结果
|
||||
*/
|
||||
@Override
|
||||
public <T> T downloadbill (Date billDate, String billType, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用查询接口
|
||||
*
|
||||
* @param tradeNoOrBillDate 支付平台订单号或者账单日期, 具体请 类型为{@link String }或者 {@link Date },类型须强制限制,类型不对应则抛出异常{@link PayErrorException}
|
||||
* @param outTradeNoBillType 商户单号或者 账单类型
|
||||
* @param transactionType 交易类型
|
||||
* @param callback 处理器
|
||||
* @return 返回支付方对应接口的结果
|
||||
*/
|
||||
@Override
|
||||
public <T> T secondaryInterface (Object tradeNoOrBillDate, String outTradeNoBillType, TransactionType transactionType, Callback<T> callback) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.egzosn.pay.union.enums;
|
||||
|
||||
import com.egzosn.pay.common.bean.TransactionType;
|
||||
import com.egzosn.pay.union.SDK.SDKConstants;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
create 2017 2017/11/4 0004
|
||||
* </pre>
|
||||
*/
|
||||
public enum UnionTransactionType implements TransactionType{
|
||||
//申码(主扫场景)
|
||||
APPLY_QR_CODE("01","07","000000","08"),
|
||||
//消费(被扫场景)
|
||||
CONSUME("01","06","000000","08"),
|
||||
//消费撤销
|
||||
CONSUME_UNDO("31","00","000000","08"),
|
||||
//查询
|
||||
QUERY("00","00","000201",""),
|
||||
//退款
|
||||
REFUND("04","00","000000","08"),
|
||||
//对账文件下载
|
||||
File_Transfer("00","00","000201","")
|
||||
;
|
||||
|
||||
/**
|
||||
* 交易类型
|
||||
*/
|
||||
private String txnType;
|
||||
/**
|
||||
* 交易子类
|
||||
*/
|
||||
private String txnSubType;
|
||||
|
||||
/**
|
||||
* 业务类型
|
||||
*/
|
||||
private String bizType;
|
||||
|
||||
/**
|
||||
* 渠道类型
|
||||
*/
|
||||
private String channelType;
|
||||
|
||||
|
||||
UnionTransactionType (String txnType, String txnSubType, String bizType, String channelType) {
|
||||
this.txnType = txnType;
|
||||
this.txnSubType = txnSubType;
|
||||
this.bizType = bizType;
|
||||
this.channelType = channelType;
|
||||
}
|
||||
|
||||
public void convertMap(Map<String ,String> contentData){
|
||||
contentData.put(SDKConstants.param_txnType, this.getTxnType());
|
||||
contentData.put(SDKConstants.param_txnSubType,this.getTxnSubType());
|
||||
contentData.put(SDKConstants.param_bizType,this.getBizType());
|
||||
contentData.put(SDKConstants.param_channelType,this.getChannelType());
|
||||
}
|
||||
|
||||
|
||||
public String getTxnType () {
|
||||
return txnType;
|
||||
}
|
||||
|
||||
public String getTxnSubType () {
|
||||
return txnSubType;
|
||||
}
|
||||
|
||||
public String getBizType () {
|
||||
return bizType;
|
||||
}
|
||||
|
||||
public String getChannelType () {
|
||||
return channelType;
|
||||
}
|
||||
|
||||
/**
|
||||
*获取交易对类型枚举
|
||||
*
|
||||
* @return 交易类型
|
||||
*/
|
||||
@Override
|
||||
public String getType () {
|
||||
return this.name();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public String getMethod () {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.egzosn.pay.union.request;
|
||||
|
||||
/**
|
||||
* @author Actinia
|
||||
* @email hayesfu@qq.com
|
||||
* <pre>
|
||||
create 2017 2017/11/4 0004
|
||||
* </pre>
|
||||
*/
|
||||
public class UnionQueryOrder {
|
||||
|
||||
private Integer payId;
|
||||
/**
|
||||
* 支付平台订单号
|
||||
*/
|
||||
private String orderId;
|
||||
/**
|
||||
* 金额
|
||||
*/
|
||||
private String txnAmt;
|
||||
/**
|
||||
* 原交易查询流水号
|
||||
*/
|
||||
private String origQryId;
|
||||
/**
|
||||
* 原交易商户订单号
|
||||
*/
|
||||
private String origOrderId;
|
||||
/**
|
||||
* 原交易商户发送交易时间:
|
||||
*/
|
||||
private String origTxnTime;
|
||||
|
||||
|
||||
public Integer getPayId() {
|
||||
return payId;
|
||||
}
|
||||
|
||||
public void setPayId(Integer payId) {
|
||||
this.payId = payId;
|
||||
}
|
||||
|
||||
public String getOrderId () {
|
||||
return orderId;
|
||||
}
|
||||
|
||||
public void setOrderId (String orderId) {
|
||||
this.orderId = orderId;
|
||||
}
|
||||
|
||||
public String getTxnAmt () {
|
||||
return txnAmt;
|
||||
}
|
||||
|
||||
public void setTxnAmt (String txnAmt) {
|
||||
this.txnAmt = txnAmt;
|
||||
}
|
||||
|
||||
public String getOrigQryId () {
|
||||
return origQryId;
|
||||
}
|
||||
|
||||
public void setOrigQryId (String origQryId) {
|
||||
this.origQryId = origQryId;
|
||||
}
|
||||
|
||||
public String getOrigOrderId () {
|
||||
return origOrderId;
|
||||
}
|
||||
|
||||
public void setOrigOrderId (String origOrderId) {
|
||||
this.origOrderId = origOrderId;
|
||||
}
|
||||
|
||||
public String getOrigTxnTime () {
|
||||
return origTxnTime;
|
||||
}
|
||||
|
||||
public void setOrigTxnTime (String origTxnTime) {
|
||||
this.origTxnTime = origTxnTime;
|
||||
}
|
||||
}
|
||||
9
pom.xml
9
pom.xml
@@ -26,7 +26,7 @@
|
||||
</developer>
|
||||
<developer>
|
||||
<name>Actinia</name>
|
||||
<email>412605202@qq.com</email>
|
||||
<email>hayesfu@qq.com</email>
|
||||
<url>https://github.com/Actinian</url>
|
||||
</developer>
|
||||
</developers>
|
||||
@@ -76,7 +76,12 @@
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.17</version>
|
||||
</dependency>
|
||||
|
||||
<!--org.bouncycastle-->
|
||||
<dependency>
|
||||
<groupId>org.bouncycastle</groupId>
|
||||
<artifactId>bcprov-debug-jdk15on</artifactId>
|
||||
<version>1.58</version>
|
||||
</dependency>
|
||||
|
||||
<!-- log4j -->
|
||||
<dependency>
|
||||
|
||||
Reference in New Issue
Block a user