杉德支付收银台支付Demo解析,聚合支付

mac2025-02-14  10

文章目录

CryptoUtil工具类 CashierPaySignServlet数据处理ServletsandPayConfig.properties 配置文件web.xml配置pom.xml配置项目结构

CryptoUtil工具类

/** * 工具类--来自官方Demo */ package cn.com.sandpay.util; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.crypto.*; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigInteger; import java.security.*; import java.security.cert.X509Certificate; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; /** * @version 2.0.0 * @ClassName: CryptoUtil * @Description: sdk加解密工具类,主要用于签名、验证、RSA加解密等 */ public class CryptoUtil { public static Logger logger = LoggerFactory.getLogger(CryptoUtil.class); /** * 数字签名函数入口 * * @param plainBytes 待签名明文字节数组 * @param privateKey 签名使用私钥 * @param signAlgorithm 签名算法 * @return 签名后的字节数组 * @throws Exception */ public static byte[] digitalSign(byte[] plainBytes, PrivateKey privateKey, String signAlgorithm) throws Exception { try { Signature signature = Signature.getInstance(signAlgorithm); signature.initSign(privateKey); signature.update(plainBytes); byte[] signBytes = signature.sign(); return signBytes; } catch (NoSuchAlgorithmException e) { throw new Exception(String.format("数字签名时没有[%s]此类算法", signAlgorithm)); } catch (InvalidKeyException e) { throw new Exception("数字签名时私钥无效", e); } catch (SignatureException e) { throw new Exception("数字签名时出现异常", e); } } /** * 验证数字签名函数入口 * * @param plainBytes 待验签明文字节数组 * @param signBytes 待验签签名后字节数组 * @param publicKey 验签使用公钥 * @param signAlgorithm 签名算法 * @return 验签是否通过 * @throws Exception */ public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, PublicKey publicKey, String signAlgorithm) throws Exception { boolean isValid = false; try { Signature signature = Signature.getInstance(signAlgorithm); signature.initVerify(publicKey); signature.update(plainBytes); isValid = signature.verify(signBytes); return isValid; } catch (NoSuchAlgorithmException e) { throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm), e); } catch (InvalidKeyException e) { throw new Exception("验证数字签名时公钥无效", e); } catch (SignatureException e) { throw new Exception("验证数字签名时出现异常", e); } } /** * 验证数字签名函数入口 * * @param plainBytes 待验签明文字节数组 * @param signBytes 待验签签名后字节数组 * @param signAlgorithm 签名算法 * @return 验签是否通过 * @throws Exception */ public static boolean verifyDigitalSign(byte[] plainBytes, byte[] signBytes, X509Certificate cert, String signAlgorithm) throws Exception { boolean isValid = false; try { Signature signature = Signature.getInstance(signAlgorithm); signature.initVerify(cert); signature.update(plainBytes); isValid = signature.verify(signBytes); return isValid; } catch (NoSuchAlgorithmException e) { throw new Exception(String.format("验证数字签名时没有[%s]此类算法", signAlgorithm)); } catch (InvalidKeyException e) { throw new Exception("验证数字签名时公钥无效", e); } catch (SignatureException e) { throw new Exception("验证数字签名时出现异常", e); } } /** * RSA加密 * * @param plainBytes 明文字节数组 * @param publicKey 公钥 * @param keyLength 密钥bit长度 * @param reserveSize padding填充字节数,预留11字节 * @param cipherAlgorithm 加解密算法,一般为RSA/ECB/PKCS1Padding * @return 加密后字节数组,不经base64编码 * @throws Exception */ public static byte[] RSAEncrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize, String cipherAlgorithm) throws Exception { int keyByteSize = keyLength / 8; // 密钥字节数 int encryptBlockSize = keyByteSize - reserveSize; // 加密块大小=密钥字节数-padding填充字节数 int nBlock = plainBytes.length / encryptBlockSize;// 计算分段加密的block数,向上取整 if ((plainBytes.length % encryptBlockSize) != 0) { // 余数非0,block数再加1 nBlock += 1; } try { Cipher cipher = Cipher.getInstance(cipherAlgorithm); cipher.init(Cipher.ENCRYPT_MODE, publicKey); // 输出buffer,大小为nBlock个keyByteSize ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * keyByteSize); // 分段加密 for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) { int inputLen = plainBytes.length - offset; if (inputLen > encryptBlockSize) { inputLen = encryptBlockSize; } // 得到分段加密结果 byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen); // 追加结果到输出buffer中 outbuf.write(encryptedBlock); } outbuf.flush(); outbuf.close(); return outbuf.toByteArray(); } catch (NoSuchAlgorithmException e) { throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm)); } catch (NoSuchPaddingException e) { throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm)); } catch (InvalidKeyException e) { throw new Exception("无效密钥", e); } catch (IllegalBlockSizeException e) { throw new Exception("加密块大小不合法", e); } catch (BadPaddingException e) { throw new Exception("错误填充模式", e); } catch (IOException e) { throw new Exception("字节输出流异常", e); } } /** * RSA解密 * * @param encryptedBytes 加密后字节数组 * @param privateKey 私钥 * @param keyLength 密钥bit长度 * @param reserveSize padding填充字节数,预留11字节 * @param cipherAlgorithm 加解密算法,一般为RSA/ECB/PKCS1Padding * @return 解密后字节数组,不经base64编码 * @throws Exception */ public static byte[] RSADecrypt(byte[] encryptedBytes, PrivateKey privateKey, int keyLength, int reserveSize, String cipherAlgorithm) throws Exception { int keyByteSize = keyLength / 8; // 密钥字节数 int decryptBlockSize = keyByteSize - reserveSize; // 解密块大小=密钥字节数-padding填充字节数 int nBlock = encryptedBytes.length / keyByteSize;// 计算分段解密的block数,理论上能整除 try { Cipher cipher = Cipher.getInstance(cipherAlgorithm); cipher.init(Cipher.DECRYPT_MODE, privateKey); // 输出buffer,大小为nBlock个decryptBlockSize ByteArrayOutputStream outbuf = new ByteArrayOutputStream(nBlock * decryptBlockSize); // 分段解密 for (int offset = 0; offset < encryptedBytes.length; offset += keyByteSize) { // block大小: decryptBlock 或 剩余字节数 int inputLen = encryptedBytes.length - offset; if (inputLen > keyByteSize) { inputLen = keyByteSize; } // 得到分段解密结果 byte[] decryptedBlock = cipher.doFinal(encryptedBytes, offset, inputLen); // 追加结果到输出buffer中 outbuf.write(decryptedBlock); } outbuf.flush(); outbuf.close(); return outbuf.toByteArray(); } catch (NoSuchAlgorithmException e) { throw new Exception(String.format("没有[%s]此类解密算法", cipherAlgorithm)); } catch (NoSuchPaddingException e) { throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm)); } catch (InvalidKeyException e) { throw new Exception("无效密钥", e); } catch (IllegalBlockSizeException e) { throw new Exception("解密块大小不合法", e); } catch (BadPaddingException e) { throw new Exception("错误填充模式", e); } catch (IOException e) { throw new Exception("字节输出流异常", e); } } public static PublicKey toPublicKey(BigInteger exponent, BigInteger modulus) throws Exception { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPublicKeySpec pubSpec = new RSAPublicKeySpec(modulus, exponent); PublicKey key = keyFactory.generatePublic(pubSpec); return key; } public static PrivateKey toPrivateKey(BigInteger exponent, BigInteger modulus) throws Exception { KeyFactory keyFactory = KeyFactory.getInstance("RSA"); RSAPrivateKeySpec prispec = new RSAPrivateKeySpec(modulus, exponent); PrivateKey key = keyFactory.generatePrivate(prispec); return key; } /** * AES加密 * * @param plainBytes 明文字节数组 * @param keyBytes 密钥字节数组 * @param keyAlgorithm 密钥算法 * @param cipherAlgorithm 加解密算法 * @param IV 随机向量 * @return 加密后字节数组,不经base64编码 * @throws Exception */ public static byte[] AESEncrypt(byte[] plainBytes, byte[] keyBytes, String keyAlgorithm, String cipherAlgorithm, String IV) throws Exception { try { // AES密钥长度为128bit、192bit、256bit,默认为128bit if (keyBytes.length % 8 != 0 || keyBytes.length < 16 || keyBytes.length > 32) { throw new Exception("AES密钥长度不合法"); } Cipher cipher = Cipher.getInstance(cipherAlgorithm); SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm); if (StringUtils.trimToNull(IV) != null) { IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes()); cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivspec); } else { cipher.init(Cipher.ENCRYPT_MODE, secretKey); } byte[] encryptedBytes = cipher.doFinal(plainBytes); return encryptedBytes; } catch (NoSuchAlgorithmException e) { throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm)); } catch (NoSuchPaddingException e) { throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm)); } catch (InvalidKeyException e) { throw new Exception("无效密钥", e); } catch (InvalidAlgorithmParameterException e) { throw new Exception("无效密钥参数", e); } catch (BadPaddingException e) { throw new Exception("错误填充模式", e); } catch (IllegalBlockSizeException e) { throw new Exception("加密块大小不合法", e); } } /** * AES解密 * * @param encryptedBytes 密文字节数组,不经base64编码 * @param keyBytes 密钥字节数组 * @param keyAlgorithm 密钥算法 * @param cipherAlgorithm 加解密算法 * @param IV 随机向量 * @return 解密后字节数组 * @throws Exception */ public static byte[] AESDecrypt(byte[] encryptedBytes, byte[] keyBytes, String keyAlgorithm, String cipherAlgorithm, String IV) throws Exception { try { // AES密钥长度为128bit、192bit、256bit,默认为128bit if (keyBytes.length % 8 != 0 || keyBytes.length < 16 || keyBytes.length > 32) { throw new Exception("AES密钥长度不合法"); } Cipher cipher = Cipher.getInstance(cipherAlgorithm); SecretKey secretKey = new SecretKeySpec(keyBytes, keyAlgorithm); if (IV != null && StringUtils.trimToNull(IV) != null) { IvParameterSpec ivspec = new IvParameterSpec(IV.getBytes()); cipher.init(Cipher.DECRYPT_MODE, secretKey, ivspec); } else { cipher.init(Cipher.DECRYPT_MODE, secretKey); } byte[] decryptedBytes = cipher.doFinal(encryptedBytes); return decryptedBytes; } catch (NoSuchAlgorithmException e) { throw new Exception(String.format("没有[%s]此类加密算法", cipherAlgorithm)); } catch (NoSuchPaddingException e) { throw new Exception(String.format("没有[%s]此类填充模式", cipherAlgorithm)); } catch (InvalidKeyException e) { throw new Exception("无效密钥", e); } catch (InvalidAlgorithmParameterException e) { throw new Exception("无效密钥参数", e); } catch (BadPaddingException e) { throw new Exception("错误填充模式", e); } catch (IllegalBlockSizeException e) { throw new Exception("解密块大小不合法", e); } } public static byte[] hexString2ByteArr(String hexStr) { return new BigInteger(hexStr, 16).toByteArray(); } public static final byte[] hexStrToBytes(String s) { byte[] bytes; bytes = new byte[s.length() / 2]; for (int i = 0; i < bytes.length; i++) { bytes[i] = (byte) Integer.parseInt(s.substring(2 * i, 2 * i + 2), 16); } return bytes; } /** * 字符数组16进制字符 * * @param bytes * @return */ public static String bytes2string(byte[] bytes, int radix) { int size = 2; if (radix == 2) { size = 8; } StringBuilder sb = new StringBuilder(bytes.length * size); for (int i = 0; i < bytes.length; i++) { int integer = bytes[i]; while (integer < 0) { integer = integer + 256; } String str = Integer.toString(integer, radix); sb.append(StringUtils.leftPad(str.toUpperCase(), size, "0")); } return sb.toString(); } }

CashierPaySignServlet数据处理Servlet

package cn.com.sandpay.demo; import cn.com.sand.pay.online.sdk.encrypt.CertUtil; import cn.com.sand.pay.online.sdk.util.ConfigurationManager; import cn.com.sand.pay.online.sdk.util.DynamicPropertyHelper; import cn.com.sandpay.util.CryptoUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import org.apache.commons.codec.binary.Base64; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; /** * 支付下单签名方法 * * @author sandpay */ public class CashierPaySignServlet extends HttpServlet { private static final Logger logger = LoggerFactory.getLogger(CashierPaySignServlet.class); private static final long serialVersionUID = 1L; /** * 加载公私钥并初始化 */ @Override public void init() throws ServletException { super.init(); try { ConfigurationManager.loadProperties(new String[]{"sandPayConfig"}); } catch (Exception e) { e.printStackTrace(); } } //开放get请求方式 @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { this.doPost(req,resp); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) { Map<String, String[]> params = req.getParameterMap(); Map<String, String> map = new HashMap<String, String>(); for (String key : params.keySet()) { String[] values = params.get(key); if (values.length > 0) { map.put(key, values[0]); } } Object ddd=JSONObject.toJSON(map); System.out.println("==================="+ddd.toString()); //报文由头部(公共参数),主体部分(商户参数)组成 // 组后台报文 JSONObject head = new JSONObject(); //版本号 //head.put("version", map.get("version")); head.put("version", "1.0"); //接口名称 //head.put("method", map.get("method")); head.put("method", "sandpay.trade.orderCreate"); //产品编码 //head.put("productId", map.get("productId")); head.put("productId", "00002000"); //接入类型 //head.put("accessType", map.get("accessType")); head.put("accessType", "1"); //商户id //head.put("mid", map.get("mid")); head.put("mid", "100211701160001"); //平台id //head.put("plMid", map.get("plMid")); head.put("plMid", ""); //渠道类型07互联网08移动端 //head.put("channelType", map.get("channelType")); head.put("channelType", "07"); //请求时间 格式:yyyyMMddhhmmss //head.put("reqTime", map.get("reqTime")); head.put("reqTime", "20191030164628"); //主体部分 JSONObject body = new JSONObject(); //商户订单号 body.put("orderCode", map.get("orderCode")); //付款方id body.put("userId", map.get("userId")); //订单金额 body.put("totalAmount", map.get("totalAmount")); //订单标题 body.put("subject", map.get("subject")); //订单描述 //订单信息详细描述JSON格式:{mallOrderCode:商城订单号 receiveAddress:收货地址 goodsDesc:商品描述 } body.put("body", map.get("body")); //订单超时时间 body.put("txnTimeOut", map.get("txnTimeOut")); //支付方式列表 body.put("payModeList", map.get("payModeList")); //异步通知地址 body.put("notifyUrl", map.get("notifyUrl")); //前台通知地址 body.put("frontUrl", map.get("frontUrl")); //商户门店编号 body.put("storeId", map.get("storeId")); //商户终端标号 body.put("terminalId", map.get("terminalId")); //操作员编号 body.put("operatorId", map.get("operatorId")); //清算模式 body.put("clearCycle", map.get("clearCycle")); //入账模式 body.put("accountingMode", map.get("accountingMode")); //风控信息域 body.put("riskRateInfo", map.get("riskRateInfo")); //业务扩展参数 body.put("bizExtendParams", map.get("bizExtendParams")); //商户扩展参数 body.put("merchExtendParams", map.get("merchExtendParams")); //扩展域 body.put("extend", map.get("extend")); //传入参数示例 // //订单描述 // JSONObject test = new JSONObject(); // test.put("mallOrderCode","mall00000000001"); // test.put("receiveAddress","上海市徐汇区田林路487号宝石园22号2楼"); // test.put("goodsDesc","杉德卡1张"); // JSONObject body = new JSONObject(); // body.put("orderCode", "sandpay20191030164628"); // body.put("userId", "C0908992"); // body.put("totalAmount", "000000000001"); // body.put("subject", "杉德收银台统测试订单标题"); // body.put("body",test); // body.put("txnTimeOut", ""); // body.put("payModeList", "[b2b,b2c,qrpay,qppay,rempay]"); // body.put("notifyUrl", "http://127.0.0.1/WebGateway/stateChangeServlet"); // body.put("frontUrl", "http://61.129.71.103:8003/jspsandpay/payReturn.jsp"); // body.put("storeId", "shmdbh001"); // body.put("terminalId", "shzdbh001"); // body.put("operatorId", "czybh001"); // body.put("clearCycle", "0"); // body.put("accountingMode", "02"); // body.put("riskRateInfo", "fkxxy"); // body.put("bizExtendParams", "yykzcs"); // body.put("merchExtendParams", "shkzcs"); // body.put("extend", "kzy"); JSONObject data = new JSONObject(); data.put("head", head); data.put("body", body); try { // 获取报文签名 String reqSign = digitalSign(data.toJSONString()); JSONObject respJson = new JSONObject(); //写入参数和签名 respJson.put("data", JSON.toJSONString(data)); respJson.put("sign", reqSign); //重定向请求到上的支付收银台接口 resp.sendRedirect("https://cashier.sandpay.com.cn/gw/web/order/create?charset=UTF-8&data="+JSON.toJSONString(data)+"&signType=01&sign="+reqSign+"&extend=kzy"); } catch (Exception e) { logger.error("CashierPayServlet post error <<<", e); } } /** * 签名方法 * * @param data 待签名数据 * @return * @throws Exception */ public static String digitalSign(String data) throws Exception { if (null == data) { return null; } else { try { // 获取密钥配置 String publicKeyPath = DynamicPropertyHelper.getStringProperty("sandpay.public.key", "").get(); String privateKeyPath = DynamicPropertyHelper.getStringProperty("sandpay.private.key", "").get(); String keyPassword = DynamicPropertyHelper.getStringProperty("sandpay.private.key.password", "").get(); // 初始化密钥信息 CertUtil.init(publicKeyPath, privateKeyPath, keyPassword); byte[] dataBytes = data.getBytes("UTF-8"); // 签名 String signData = new String(Base64.encodeBase64(CryptoUtil.digitalSign(dataBytes, CertUtil.getPrivateKey(), "SHA1WithRSA")), "UTF-8"); logger.info("digitalSign(String) =>>sign:{}", signData); return URLEncoder.encode(signData, "UTF-8"); } catch (Exception var6) { logger.error("digitalSign(String, String)", var6); throw new Exception("签名异常", var6); } } } }

sandPayConfig.properties 配置文件

#--杉德公钥-放入resources目录下的对应公钥文件 sandpay.public.key=classpath:sand.cer #--商户号对应的私钥和密码-放入resources目录下的对应私钥文件 sandpay.private.key=classpath:MID_RSA_PRIVATE_KEY_100211701160001.pfx ##--私钥密码--导出私钥时设置的密码--导出方法官方有介绍 sandpay.private.key.password=123456 #--商户基础信息 #sandpay.merch.mid=16640704 sandpay.merch.mid=S6848437//商户号 sandpay.merch.plmid= //平台商户号 sandpay.merch.productcode=00002000 //平台编号 #--支付网关地址 sandpay.gateWay.url=https://cashier.sandpay.com.cn/gw/ sandpay.gateWay.front.url=http://商户前台跳转地址 sandpay.gateWay.backnotice.url=http\://\u00E5\u0095\u0086\u00E6\u0088\u00B7\u00E5\u0090\u008E\u00E7\u00AB\u00AF\u00E9\u0080\u009A\u00E7\u009F\u00A5\u00E6\u008E\u00A5\u00E6\u0094\u00B6\u00E5\u009C\u00B0\u00E5\u009D\u0080

web.xml配置

<?xml version="1.0" encoding="UTF-8"?> <web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0"> //设置servlet为启动项 <welcome-file-list> <welcome-file>/cashierPay</welcome-file> <welcome-file>/cashierPay</welcome-file> </welcome-file-list> <servlet> <servlet-name>cashierPay</servlet-name> <servlet-class>cn.com.sandpay.demo.CashierPaySignServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>cashierPay</servlet-name> <url-pattern>/cashierPay</url-pattern> </servlet-mapping> </web-app>

pom.xml配置

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>cn.com.sand.pay</groupId> <artifactId>sandpay-cashier-demo</artifactId> <version>1.0.0</version> <packaging>war</packaging> <name>sandpay-cashier-demo</name> <url>http://maven.apache.org</url> <repositories> <repository> <id>mvnrepository2</id> <url>http://172.28.250.84:8084/nexus/content/groups/public/</url> </repository> </repositories> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- 测试核心包 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> </dependency> <!-- servlet核心包 --> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <!-- http核心包 --> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpcore</artifactId> <version>4.4.1</version> </dependency> <!-- 接口集成sdk --> <dependency> <groupId>cn.com.sand.pay</groupId> <artifactId>sandpay-online-sdk</artifactId> <version>2.0.1</version> <scope>system</scope> <systemPath>${project.basedir}/sandpay-online-sdk-2.0.1.jar</systemPath> </dependency> <!-- fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>com.netflix.archaius</groupId> <artifactId>archaius-core</artifactId> <version>0.6.0</version> </dependency> <dependency> <groupId>net.iharder</groupId> <artifactId>base64</artifactId> <version>2.3.9</version> </dependency> <dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.13</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.3</version> </dependency> <dependency> <groupId>commons-lang</groupId> <artifactId>commons-lang</artifactId> <version>2.6</version> </dependency> </dependencies> <build> <plugins> <!-- compiler插件, 设定JDK版本 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.7</source> <target>1.7</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.mortbay.jetty</groupId> <artifactId>maven-jetty-plugin</artifactId> <version>6.1.26</version> <configuration> <stopKey>foo</stopKey> <stopPort>9966</stopPort> <scanIntervalSeconds>10</scanIntervalSeconds> <connectors> <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector"> <port>8081</port> <maxIdleTime>60000</maxIdleTime> </connector> </connectors> </configuration> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <configuration> <nonFilteredFileExtensions> <nonFilteredFileExtension>pfx</nonFilteredFileExtension> <nonFilteredFileExtension>cer</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> </plugin> </plugins> </build> </project>

项目结构

注意在搭建项目时使用阿里maven仓库。对应官方sdk请自行下载。

最新回复(0)