杨杰 1 gadu atpakaļ
vecāks
revīzija
cb739b63a9
39 mainītis faili ar 1245 papildinājumiem un 21 dzēšanām
  1. 20 1
      pay.sql
  2. 6 1
      pom.xml
  3. 1 1
      src/main/java/com/llisoft/pay/common/CodeEnum.java
  4. 28 0
      src/main/java/com/llisoft/pay/common/Constant.java
  5. 56 0
      src/main/java/com/llisoft/pay/config/ExceptionFilterConfig.java
  6. 93 0
      src/main/java/com/llisoft/pay/config/ExceptionHandlerConfig.java
  7. 38 0
      src/main/java/com/llisoft/pay/config/MtaException.java
  8. 53 0
      src/main/java/com/llisoft/pay/controller/ApiController.java
  9. 6 5
      src/main/java/com/llisoft/pay/controller/CallbackAliPayController.java
  10. 45 0
      src/main/java/com/llisoft/pay/controller/CallbackWxPayController.java
  11. 1 0
      src/main/java/com/llisoft/pay/controller/OrderController.java
  12. 3 2
      src/main/java/com/llisoft/pay/controller/WxPayController.java
  13. 2 1
      src/main/java/com/llisoft/pay/dao/AppDao.java
  14. 1 0
      src/main/java/com/llisoft/pay/dao/ItemDao.java
  15. 1 0
      src/main/java/com/llisoft/pay/dao/OrderDao.java
  16. 23 0
      src/main/java/com/llisoft/pay/dao/PayDao.java
  17. 1 0
      src/main/java/com/llisoft/pay/entity/App.java
  18. 1 0
      src/main/java/com/llisoft/pay/entity/Item.java
  19. 1 0
      src/main/java/com/llisoft/pay/entity/Order.java
  20. 153 0
      src/main/java/com/llisoft/pay/entity/Pay.java
  21. 121 0
      src/main/java/com/llisoft/pay/service/ApiService.java
  22. 2 1
      src/main/java/com/llisoft/pay/service/AppService.java
  23. 2 1
      src/main/java/com/llisoft/pay/service/OrderService.java
  24. 2 2
      src/main/java/com/llisoft/pay/service/PayAliService.java
  25. 3 2
      src/main/java/com/llisoft/pay/service/PayService.java
  26. 3 2
      src/main/java/com/llisoft/pay/service/PayWxService.java
  27. 232 0
      src/main/java/com/llisoft/pay/service/PayWxV3Service.java
  28. 24 0
      src/main/java/com/llisoft/pay/vo/ApiInfoRequestVo.java
  29. 42 0
      src/main/java/com/llisoft/pay/vo/ApiInfoResponseVo.java
  30. 20 0
      src/main/java/com/llisoft/pay/vo/ApiPayAliAppResponseVo.java
  31. 37 0
      src/main/java/com/llisoft/pay/vo/ApiPayRequestVo.java
  32. 31 0
      src/main/java/com/llisoft/pay/vo/ApiPayWxAppResponseVo.java
  33. 31 0
      src/main/java/com/llisoft/pay/vo/ApiPayWxJsApiResponseVo.java
  34. 31 0
      src/main/java/com/llisoft/pay/vo/ApiPayWxNativeResponseVo.java
  35. 1 0
      src/main/java/com/llisoft/pay/vo/OrderAddRequestVo.java
  36. 1 0
      src/main/java/com/llisoft/pay/vo/OrderPayRequestVo.java
  37. 124 0
      src/main/java/com/llisoft/pay/vo/ResponseVo.java
  38. 3 0
      src/main/resources/application.yml
  39. 2 2
      src/test/java/com/llisoft/pay/ServiceTest.java

+ 20 - 1
pay.sql

@@ -1,3 +1,22 @@
+
+CREATE TABLE `mta_pay` (
+  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
+  `pid` varchar(255) NOT NULL COMMENT '支付号',
+  `type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '支付类型(1支付宝/2微信)',
+  `status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '支付状态(1未支付/2已支付)',
+  `money` int(11) NOT NULL DEFAULT '0' COMMENT '支付金额(分)',
+  `tital` varchar(255) DEFAULT NULL COMMENT '商品描述(第三方平台显示)',
+  `flag` tinyint(4) NOT NULL DEFAULT '0' COMMENT '支付成功标记(1异步通知/2同步回调/3主动查询/4对账)',
+  `pnum` varchar(255) DEFAULT NULL COMMENT '第三方交易号(由第三方通知返回)',
+  `ptime` datetime DEFAULT NULL COMMENT '支付时间',
+  `ctime` datetime DEFAULT NULL COMMENT '创建时间',
+  `utime` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `pid` (`pid`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+-- 以下表弃用
+
 CREATE TABLE `mta_pay_app` (
   `app_id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
   `app_key` varchar(255) NOT NULL COMMENT '业务唯一标识',
@@ -41,4 +60,4 @@ CREATE TABLE `mta_pay_order` (
   `update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
   PRIMARY KEY (`order_id`),
   UNIQUE KEY `order_num` (`order_num`)
-) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
+) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

+ 6 - 1
pom.xml

@@ -36,11 +36,16 @@
 			<groupId>mysql</groupId>
 			<artifactId>mysql-connector-java</artifactId>
 		</dependency>
-		<dependency>
+		<dependency><!-- 支付宝 -->
 			<groupId>com.alipay.sdk</groupId>
 			<artifactId>alipay-sdk-java</artifactId>
 			<version>3.1.0</version>
 		</dependency>
+		<dependency><!-- 微信支付 -->
+		  <groupId>com.github.wechatpay-apiv3</groupId>
+		  <artifactId>wechatpay-java</artifactId>
+		  <version>0.2.12</version>
+		</dependency>
 		<dependency><!-- jackson解析xml -->
 			<groupId>com.fasterxml.jackson.dataformat</groupId>
 			<artifactId>jackson-dataformat-xml</artifactId>

+ 1 - 1
src/main/java/com/llisoft/pay/vo/CodeEnum.java → src/main/java/com/llisoft/pay/common/CodeEnum.java

@@ -1,4 +1,4 @@
-package com.llisoft.pay.vo;
+package com.llisoft.pay.common;
 
 /**
  * 返回状态枚举

+ 28 - 0
src/main/java/com/llisoft/pay/common/Constant.java

@@ -0,0 +1,28 @@
+package com.llisoft.pay.common;
+
+/**
+ * 公共常量
+ * @author YangJie [2018年12月27日]
+ */
+public class Constant {
+	
+	// 支付状态 未支付
+	public static final byte STATUS_WAIT = 1;
+	// 支付状态 已支付
+	public static final byte STATUS_PAYED = 2;
+	
+	// 支付类型 支付宝
+	public static final byte TYPE_ALI = 1;
+	// 支付类型 微信
+	public static final byte TYPE_WX = 2;
+	
+	// 支付标记 - 异步通知 
+	public static final byte FLAG_NOTIFY = 1;
+	// 支付标记 - 同步回调 
+	public static final byte FLAG_RETURN = 2;
+	// 支付标记 - 主动查询 
+	public static final byte FLAG_QUERY = 3;
+	// 支付标记 - 对账 
+	public static final byte FLAG_CHECK = 4;
+	
+}

+ 56 - 0
src/main/java/com/llisoft/pay/config/ExceptionFilterConfig.java

@@ -0,0 +1,56 @@
+package com.llisoft.pay.config;
+
+import java.io.IOException;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.filter.OncePerRequestFilter;
+
+import com.llisoft.pay.common.CodeEnum;
+import com.llisoft.pay.util.JsonUtil;
+import com.llisoft.pay.vo.ResponseVo;
+
+/**
+ * 全局异常过滤器
+ * 处理在filter中抛出异常时正常返回json
+ * 使过滤器生效,必须注入到容器并设置顺序到最前
+ * @author YangJie [2019年10月25日]
+ */
+@Configuration
+@Order(Integer.MIN_VALUE + 1) // 指定顺序,需要在跨域过滤器之后,其他过滤器之前
+public class ExceptionFilterConfig extends OncePerRequestFilter {
+	
+	private Logger logger = LoggerFactory.getLogger(ExceptionFilterConfig.class);
+
+	@Override
+	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
+			throws ServletException, IOException {
+		try {
+			filterChain.doFilter(request, response);
+		} catch (Throwable exception) { // 抛异常情况
+			if(!(exception instanceof IOException)) {
+				logger.error("过滤器异常:{}", exception.getMessage());
+			}
+			response.setStatus(HttpStatus.OK.value()); // 状态码200
+			response.setContentType("application/json; charset=utf-8");
+			CodeEnum codeEnum = CodeEnum.C500;
+			if (exception instanceof MtaException) {
+				codeEnum = ((MtaException)exception).getCodeEnum();
+			}
+			try { // 返回json
+				response.getWriter().write(JsonUtil.toJson(ResponseVo.build(codeEnum)));
+			} catch (Exception e) {
+				// e.printStackTrace();
+			}
+		}
+	}
+
+}

+ 93 - 0
src/main/java/com/llisoft/pay/config/ExceptionHandlerConfig.java

@@ -0,0 +1,93 @@
+package com.llisoft.pay.config;
+
+import java.util.Objects;
+
+import org.apache.catalina.connector.ClientAbortException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.converter.HttpMessageNotReadableException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.servlet.NoHandlerFoundException;
+
+import com.llisoft.pay.common.CodeEnum;
+import com.llisoft.pay.vo.ResponseVo;
+
+/**
+ * 统一处理业务异常 controller
+ * 只能拦截到controller层的异常
+ * 如需拦截404等系统级异常,需要有如下配置
+ * spring.resources.addMappings: false #不为工程中的资源文件建立映射
+ * spring.mvc.throwExceptionIfNoHandlerFound: true #出现异常时直接抛出
+ * @author YangJie [2018年12月26日]
+ */
+@RestControllerAdvice
+public class ExceptionHandlerConfig {
+	
+	private Logger logger = LoggerFactory.getLogger(ExceptionHandlerConfig.class);
+	
+
+    /**
+     * 入参空
+     * @param exception
+     * @return
+     */
+    @ExceptionHandler(HttpMessageNotReadableException.class)
+    public ResponseVo<String> exception(HttpMessageNotReadableException exception){
+    	logger.warn("入参异常: {}", exception.getMessage());
+        return ResponseVo.build(CodeEnum.C400);
+    }
+    
+    /**
+     * 入参检验失败
+     * @param exception
+     * @return
+     */
+    @ExceptionHandler(MethodArgumentNotValidException.class)
+    public ResponseVo<String> exception(MethodArgumentNotValidException exception){
+    	logger.warn("入参异常: {}", exception.getMessage());
+    	return ResponseVo.build(CodeEnum.C400.getCode(), exception.getBindingResult().getFieldError().getDefaultMessage());
+    }
+    
+    /**
+     * 业务异常
+     * @param exception
+     * @return
+     */
+    @ExceptionHandler(MtaException.class)
+    public ResponseVo<String> exception(MtaException exception){
+    	CodeEnum codeEnum = exception.getCodeEnum();
+    	if (Objects.nonNull(codeEnum)) {
+    		return ResponseVo.build(codeEnum.getCode(), codeEnum.getMsg());
+		}
+    	logger.warn("业务异常: {}", exception.getMessage());
+    	return ResponseVo.build(CodeEnum.FAIL.getCode(), exception.getMessage());
+    }
+    
+    /**
+     * 地址异常
+     * @param exception
+     * @return
+     */
+    @ExceptionHandler(NoHandlerFoundException.class)
+    public ResponseVo<String> exception(NoHandlerFoundException exception){
+    	logger.warn("地址异常: {}", exception.getMessage());
+    	return ResponseVo.build(CodeEnum.C404);
+    }
+    
+    /**
+     * 默认异常
+     * @param exception
+     * @return
+     */
+    @ExceptionHandler(Exception.class)
+    public ResponseVo<String> exception(Exception exception){
+    	// org.apache.catalina.connector.ClientAbortException: java.io.IOException: Broken pipe
+    	if(!(exception instanceof ClientAbortException)) {
+    		logger.error("服务异常", exception);
+    	}
+    	return ResponseVo.build(CodeEnum.C500);
+    }
+    
+}

+ 38 - 0
src/main/java/com/llisoft/pay/config/MtaException.java

@@ -0,0 +1,38 @@
+package com.llisoft.pay.config;
+
+import com.llisoft.pay.common.CodeEnum;
+
+/**
+ * 自定义业务异常
+ * @author YangJie [2019年1月4日]
+ */
+@SuppressWarnings("serial")
+public class MtaException extends RuntimeException {
+	
+	private CodeEnum codeEnum;
+
+	
+	public MtaException(String msg) {
+		super(msg);
+	}
+
+	public MtaException(CodeEnum codeEnum) {
+		super(codeEnum.getMsg());
+		this.codeEnum = codeEnum;
+	}
+
+	
+	public static MtaException build(String msg) {
+		return new MtaException(msg);
+	}
+	
+	public static MtaException build(CodeEnum codeEnum) {
+		return new MtaException(codeEnum);
+	}
+	
+
+	public CodeEnum getCodeEnum() {
+		return codeEnum;
+	}
+
+}

+ 53 - 0
src/main/java/com/llisoft/pay/controller/ApiController.java

@@ -0,0 +1,53 @@
+package com.llisoft.pay.controller;
+
+import javax.validation.Valid;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import com.llisoft.pay.service.ApiService;
+import com.llisoft.pay.vo.ApiInfoRequestVo;
+import com.llisoft.pay.vo.ApiInfoResponseVo;
+import com.llisoft.pay.vo.ApiPayAliAppResponseVo;
+import com.llisoft.pay.vo.ApiPayRequestVo;
+import com.llisoft.pay.vo.ApiPayWxAppResponseVo;
+import com.llisoft.pay.vo.ResponseVo;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * 新版接口设计方案
+ * 按产品拆分不同接口
+ * @author YangJie [2023年12月20日]
+ */
+@Api(tags="支付API")
+@RestController
+public class ApiController{
+	
+	@Autowired
+	private ApiService apiService;
+	
+	
+	@ApiOperation(value="查询 公用")
+	@PostMapping("/info")
+	public ResponseVo<ApiInfoResponseVo> info(@Valid @RequestBody ApiInfoRequestVo requestVo) throws Exception{
+		return ResponseVo.success(apiService.info(requestVo.getPid()));
+	}
+	
+	@ApiOperation(value="青题库 APP 微信支付")
+	@PostMapping("/qingtiku/app/wx")
+	public ResponseVo<ApiPayWxAppResponseVo> qingtikuAppWx(@Valid @RequestBody ApiPayRequestVo requestVo) throws Exception{
+		String appid = "";
+		return ResponseVo.success(apiService.appQinggu(appid, requestVo.getpid()));
+	}
+	
+	@ApiOperation(value="青题库 APP 支付宝")
+	@PostMapping("/qingtiku/app/ali")
+	public ResponseVo<ApiPayAliAppResponseVo> qingtikuAppAli(@Valid @RequestBody ApiPayRequestVo requestVo) throws Exception{
+		return ResponseVo.success(null);
+	}
+	
+}

+ 6 - 5
src/main/java/com/llisoft/pay/controller/AliPayController.java → src/main/java/com/llisoft/pay/controller/CallbackAliPayController.java

@@ -14,20 +14,21 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import com.llisoft.pay.service.AliPayService;
+import com.llisoft.pay.service.PayAliService;
 
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 
 @Api(tags="支付宝回调")
 @Controller
-@RequestMapping("/alipay")
-public class AliPayController {
+//@RequestMapping("/callback/alipay")
+@RequestMapping("/alipay") // 兼容旧旧接口,找机会替换成上面路径
+public class CallbackAliPayController {
 	
-	private Logger logger = LoggerFactory.getLogger(AliPayController.class);
+	private Logger logger = LoggerFactory.getLogger(CallbackAliPayController.class);
 	
 	@Autowired
-	private AliPayService aliPayService;
+	private PayAliService aliPayService;
 	
 	
 	@ApiOperation(value="同步回调")

+ 45 - 0
src/main/java/com/llisoft/pay/controller/CallbackWxPayController.java

@@ -0,0 +1,45 @@
+package com.llisoft.pay.controller;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.util.StreamUtils;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import com.llisoft.pay.service.PayWxService;
+import com.llisoft.pay.util.XmlUtil;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+
+@Api(tags="微信支付回调")
+@Controller
+@RequestMapping("/callback/wxpay")
+public class CallbackWxPayController {
+	
+	private Logger logger = LoggerFactory.getLogger(CallbackWxPayController.class);
+
+	@Autowired
+	private PayWxService wxPayService;
+	
+	
+	@ApiOperation(value="异步通知")
+	@PostMapping(value="/notify")
+	public @ResponseBody String notify(HttpServletRequest request) throws Exception {
+		// https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_7&index=8
+		String xml = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
+		logger.debug("收到微信异步通知: {}", xml);
+		Map<String, String> resultMap = XmlUtil.toObject(xml, Map.class, String.class, String.class);
+		logger.debug("解析异步通知内容: {}", resultMap);
+		return wxPayService.dispose(resultMap) ? "success" : "";
+	}
+	
+}

+ 1 - 0
src/main/java/com/llisoft/pay/controller/OrderController.java

@@ -23,6 +23,7 @@ import io.swagger.annotations.ApiOperation;
 @Api(tags="支付订单")
 @RestController
 @RequestMapping("/order")
+@Deprecated // 接口升级 > ApiController
 public class OrderController{
 	
 	private Logger logger = LoggerFactory.getLogger(OrderController.class);

+ 3 - 2
src/main/java/com/llisoft/pay/controller/WxPayController.java

@@ -14,7 +14,7 @@ import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 
-import com.llisoft.pay.service.WxPayService;
+import com.llisoft.pay.service.PayWxService;
 import com.llisoft.pay.util.XmlUtil;
 
 import io.swagger.annotations.Api;
@@ -23,12 +23,13 @@ import io.swagger.annotations.ApiOperation;
 @Api(tags="微信支付回调")
 @Controller
 @RequestMapping("/wxpay")
+@Deprecated // 升级SDKv3 > CallbackWxPayController
 public class WxPayController {
 	
 	private Logger logger = LoggerFactory.getLogger(WxPayController.class);
 
 	@Autowired
-	private WxPayService wxPayService;
+	private PayWxService wxPayService;
 	
 	
 	@ApiOperation(value="异步通知")

+ 2 - 1
src/main/java/com/llisoft/pay/dao/AppDao.java

@@ -6,10 +6,11 @@ import org.apache.ibatis.annotations.Select;
 import com.llisoft.pay.entity.App;
 
 @Mapper
+@Deprecated
 public interface AppDao {
 
 	@Select("select * from mta_pay_app where app_id=#{appId}")
-	App select(int appId);
+	App select(String appId);
 	
 	@Select("select * from mta_pay_app where app_key=#{appKey}")
 	App selectByAppKey(String appKey);

+ 1 - 0
src/main/java/com/llisoft/pay/dao/ItemDao.java

@@ -10,6 +10,7 @@ import org.apache.ibatis.annotations.Update;
 import com.llisoft.pay.entity.Item;
 
 @Mapper
+@Deprecated
 public interface ItemDao {
 
 	@Select("select * from mta_pay_item where pay_id=#{payId}")

+ 1 - 0
src/main/java/com/llisoft/pay/dao/OrderDao.java

@@ -10,6 +10,7 @@ import org.apache.ibatis.annotations.Update;
 import com.llisoft.pay.entity.Order;
 
 @Mapper
+@Deprecated
 public interface OrderDao {
 
 	@Select("select * from mta_pay_order where order_id=#{orderId}")

+ 23 - 0
src/main/java/com/llisoft/pay/dao/PayDao.java

@@ -0,0 +1,23 @@
+package com.llisoft.pay.dao;
+
+import org.apache.ibatis.annotations.Insert;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+import org.apache.ibatis.annotations.Update;
+
+import com.llisoft.pay.entity.Pay;
+
+@Mapper
+public interface PayDao {
+	
+	@Select("select * from mta_pay where pid=#{pid}")
+	Pay selectByPid(String pid);
+	
+    @Insert("insert into mta_pay (pid,type,status,money,title,ctime) values (#{pid},#{type},#{status},#{money},#{title},now())")
+    boolean insert(Pay item);
+
+    @Update("update mta_pay set status=#{status},flag=#{flag},pnum=#{pnum},ptime=now() where paynum=#{paynum}")
+	boolean update(@Param("paynum")String paynum, @Param("status")byte status, @Param("flag")byte flag, @Param("pnum")String pnum);
+	
+}

+ 1 - 0
src/main/java/com/llisoft/pay/entity/App.java

@@ -6,6 +6,7 @@ import java.util.Date;
  * 
  * 数据库实体, 禁止人为改动
  */
+@Deprecated
 public class App {
     /**
      * ID

+ 1 - 0
src/main/java/com/llisoft/pay/entity/Item.java

@@ -6,6 +6,7 @@ import java.util.Date;
  * 
  * 数据库实体, 禁止人为改动
  */
+@Deprecated
 public class Item {
     /**
      * ID

+ 1 - 0
src/main/java/com/llisoft/pay/entity/Order.java

@@ -6,6 +6,7 @@ import java.util.Date;
  * 
  * 数据库实体, 禁止人为改动
  */
+@Deprecated
 public class Order {
     /**
      * ID

+ 153 - 0
src/main/java/com/llisoft/pay/entity/Pay.java

@@ -0,0 +1,153 @@
+package com.llisoft.pay.entity;
+
+import java.util.Date;
+
+/**
+ * 
+ * 数据库实体, 禁止人为改动
+ */
+public class Pay {
+    /**
+     * ID
+     */
+    private int id;
+
+    /**
+     * 支付号
+     */
+    private String pid;
+
+    /**
+     * 支付类型(1支付宝/2微信)
+     */
+    private int type;
+
+    /**
+     * 支付状态(1未支付/2已支付)
+     */
+    private int status;
+
+    /**
+     * 支付金额(分)
+     */
+    private int money;
+
+    /**
+     * 商品描述(第三方平台显示)
+     */
+    private int title;
+
+    /**
+     * 支付成功标记(1异步通知/2同步回调/3主动查询/4对账)
+     */
+    private int flag;
+
+    /**
+     * 支付时间
+     */
+    private Date pime;
+
+    /**
+     * 第三方交易号(由第三方通知返回)
+     */
+    private String pnum;
+
+    /**
+     * 创建时间
+     */
+    private Date ctime;
+
+    /**
+     * 更新时间
+     */
+    private Date utime;
+
+	public int getId() {
+		return id;
+	}
+
+	public void setId(int id) {
+		this.id = id;
+	}
+
+	public String getPid() {
+		return pid;
+	}
+
+	public void setPid(String pid) {
+		this.pid = pid;
+	}
+
+	public int getType() {
+		return type;
+	}
+
+	public void setType(int type) {
+		this.type = type;
+	}
+
+	public int getStatus() {
+		return status;
+	}
+
+	public void setStatus(int status) {
+		this.status = status;
+	}
+
+	public int getMoney() {
+		return money;
+	}
+
+	public void setMoney(int money) {
+		this.money = money;
+	}
+
+	public int getTitle() {
+		return title;
+	}
+
+	public void setTitle(int title) {
+		this.title = title;
+	}
+
+	public int getFlag() {
+		return flag;
+	}
+
+	public void setFlag(int flag) {
+		this.flag = flag;
+	}
+
+	public Date getPime() {
+		return pime;
+	}
+
+	public void setPime(Date pime) {
+		this.pime = pime;
+	}
+
+	public String getPnum() {
+		return pnum;
+	}
+
+	public void setPnum(String pnum) {
+		this.pnum = pnum;
+	}
+
+	public Date getCtime() {
+		return ctime;
+	}
+
+	public void setCtime(Date ctime) {
+		this.ctime = ctime;
+	}
+
+	public Date getUtime() {
+		return utime;
+	}
+
+	public void setUtime(Date utime) {
+		this.utime = utime;
+	}
+
+}

+ 121 - 0
src/main/java/com/llisoft/pay/service/ApiService.java

@@ -0,0 +1,121 @@
+package com.llisoft.pay.service;
+
+import java.util.Objects;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.llisoft.pay.common.Constant;
+import com.llisoft.pay.config.MtaException;
+import com.llisoft.pay.dao.ItemDao;
+import com.llisoft.pay.dao.OrderDao;
+import com.llisoft.pay.entity.App;
+import com.llisoft.pay.entity.Item;
+import com.llisoft.pay.entity.Order;
+import com.llisoft.pay.util.CodeUtil;
+import com.llisoft.pay.vo.ApiAddResponseVo;
+import com.llisoft.pay.vo.ApiPayWxAppResponseVo;
+import com.llisoft.pay.vo.ApiInfoResponseVo;
+
+@Service
+public class ApiService {
+	
+	private Logger logger = LoggerFactory.getLogger(ApiService.class);
+	
+	
+	@Autowired
+	private ItemDao payDao;
+	@Autowired
+	private OrderDao orderDao;
+	@Autowired
+	private PayAliService payAliService;
+	@Autowired
+	private PayWxV3Service payWxV3Service;
+	
+	
+	/**
+	 * 下单
+	 * @param money 金额(分)
+	 * @param title 订单描述
+	 * @return
+	 */
+	public ApiAddResponseVo add(int money, String title) {
+		Order order = new Order();
+		order.setOrderNum(CodeUtil.time()); // 当前时间+5位随机数
+		order.setOrderMoney(money); // 订单金额(分)
+		order.setOrderTitle(title); // 订单描述
+		order.setOrderStatus(Constant.STATUS_WAIT);
+		orderDao.insert(order);
+		logger.debug("添加订单成功: {}", order.getOrderNum());
+		ApiAddResponseVo responseVo = new ApiAddResponseVo();
+		responseVo.setId(order.getOrderNum());
+		responseVo.setMoney(money);
+		return responseVo;
+	}
+	
+	/**
+	 * 查询
+	 * @param id orderNum
+	 * @return
+	 */
+	public ApiInfoResponseVo info(String id) {
+		Order order = orderDao.selectByOrderNum(id);
+		if(Objects.isNull(order)) {
+			throw MtaException.build("订单不存在:" + id);
+		}
+		ApiInfoResponseVo responseVo = new ApiInfoResponseVo();
+		responseVo.setPid(order.getOrderNum());
+		responseVo.setPayed(order.getOrderStatus() == Constant.STATUS_PAYED);
+		return responseVo;
+	}
+	
+	/**
+	 * 支付 栋科
+	 * @param id orderNum
+	 * @param type 支付方式(1支付宝,2微信)
+	 * @return
+	 */
+	public ApiPayWxAppResponseVo payDongke(String appid, String id, byte type) {
+		Order order = orderDao.selectByOrderNum(id);
+		if(Objects.isNull(order)) {
+			throw MtaException.build("订单不存在:" + id);
+		}
+		if(order.getOrderStatus() == Constant.STATUS_PAYED){
+			throw MtaException.build("订单已支付:" + id);
+		}
+		// 添加支付记录
+		Item item = new Item();
+		item.setPayNum(CodeUtil.uuid());
+		item.setPayType(type);
+		item.setOrderId(order.getOrderId());
+		item.setPayMoney(order.getOrderMoney());
+		item.setPayStatus(Constant.STATUS_WAIT);
+		payDao.insert(item);
+		// 发起支付
+		if (item.getPayType() == Constant.TYPE_ALI) { // 支付宝
+
+		}else if (item.getPayType() == Constant.TYPE_WX) { // 微信
+			payWxV3Service.appDongke(appid, item.getPayNum(), item.getPayMoney(), order.getOrderTitle());
+			return wxPayService.pay(payNum, order.getOrderMoney(), order.getOrderTitle());
+		}
+		
+		
+		
+		String payNum = payService.add(payType, order.getOrderMoney(), order.getOrderId());
+		return payService.pay(payNum, isMobile);
+	}
+	
+	/**
+	 * 支付 青谷
+	 * @param id orderNum
+	 * @param type 支付方式(1支付宝,2微信)
+	 * @return
+	 */
+	public ApiPayWxAppResponseVo payQinggu(String appid, String id, byte type) {
+		// TODO Auto-generated method stub
+		return null;
+	}
+	
+}

+ 2 - 1
src/main/java/com/llisoft/pay/service/AppService.java

@@ -16,6 +16,7 @@ import com.llisoft.pay.entity.Order;
 import com.llisoft.pay.util.HttpUtil;
 
 @Service
+@Deprecated // 升级服务,取消app设计
 public class AppService {
 	
 	private static Logger logger = LoggerFactory.getLogger(AppService.class);
@@ -48,7 +49,7 @@ public class AppService {
 	 * @param body
 	 */
 	@Async
-	public void notify(int appId, String orderNum, String body) {
+	public void notify(String appId, String orderNum, String body) {
 		App app = appDao.select(appId);
 		String notifyUrl = this.packUrl(app.getNotifyUrl(), orderNum);
 		if(Objects.isNull(notifyUrl) || notifyUrl.trim().isEmpty()) {

+ 2 - 1
src/main/java/com/llisoft/pay/service/OrderService.java

@@ -16,6 +16,7 @@ import com.llisoft.pay.util.JsonUtil;
 
 
 @Service
+@Deprecated // 升级sdk > ApiService
 public class OrderService {
 	
 	// 支付状态 未支付
@@ -62,7 +63,7 @@ public class OrderService {
 		order.setOrderMoney(orderMoney);
 		order.setOrderTitle(orderTitle); // 订单描述
 		order.setOrderStatus(STATUS_WAIT);
-		order.setAppId(app.getAppId());
+		order.setAppId(String.valueOf(app.getAppId()));
 		orderDao.insert(order);
 		logger.debug("添加订单成功: {}", orderNum);
 		return orderNum;

+ 2 - 2
src/main/java/com/llisoft/pay/service/AliPayService.java → src/main/java/com/llisoft/pay/service/PayAliService.java

@@ -28,9 +28,9 @@ import com.llisoft.pay.util.JsonUtil;
  * 支付宝支付
  */
 @Service
-public class AliPayService {
+public class PayAliService {
 	
-	private Logger logger = LoggerFactory.getLogger(AliPayService.class);
+	private Logger logger = LoggerFactory.getLogger(PayAliService.class);
 	
 	@Value("${mta.domain}")
 	private String domain;

+ 3 - 2
src/main/java/com/llisoft/pay/service/PayService.java

@@ -15,6 +15,7 @@ import com.llisoft.pay.entity.Order;
 import com.llisoft.pay.util.CodeUtil;
 
 @Service
+@Deprecated // 升级sdk > ApiService
 public class PayService {
 	
 	// 支付状态 未支付
@@ -44,9 +45,9 @@ public class PayService {
 	@Autowired
 	private OrderDao orderDao;
 	@Autowired
-	private AliPayService aliPayService;
+	private PayAliService aliPayService;
 	@Autowired
-	private WxPayService wxPayService;
+	private PayWxService wxPayService;
 	@Autowired
 	private OrderService orderService;
 	

+ 3 - 2
src/main/java/com/llisoft/pay/service/WxPayService.java → src/main/java/com/llisoft/pay/service/PayWxService.java

@@ -23,9 +23,10 @@ import com.llisoft.pay.util.XmlUtil;
  * 微信支付
  */
 @Service
-public class WxPayService {
+@Deprecated // 升级sdk > PayWxV3Service
+public class PayWxService {
 	
-	private Logger logger = LoggerFactory.getLogger(WxPayService.class);
+	private Logger logger = LoggerFactory.getLogger(PayWxService.class);
 	
 	/** 微信接口 统一下单 */
 	public static final String WX_API_ORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";

+ 232 - 0
src/main/java/com/llisoft/pay/service/PayWxV3Service.java

@@ -0,0 +1,232 @@
+package com.llisoft.pay.service;
+
+import java.util.Objects;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import com.llisoft.pay.util.BeanUtil;
+import com.llisoft.pay.util.JsonUtil;
+import com.llisoft.pay.vo.ApiPayWxAppResponseVo;
+import com.llisoft.pay.vo.ApiPayWxJsApiResponseVo;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+
+/**
+ * 微信支付v3
+ */
+@Service
+public class PayWxV3Service {
+	
+	private Logger logger = LoggerFactory.getLogger(PayWxV3Service.class);
+	
+	@Value("${mta.domain}")
+	private String domain;
+	@Value("${mta.wxpay.keyPathDongke}")
+	private String keyPathDongke;
+	@Value("${mta.wxpay.keyPathQinggu}")
+	private String keyPathQinggu;
+	
+	
+	// 商户号
+	private static String mchidDongke = "1570392471";
+	private static String mchidQinggu = "";
+	// 使用自动更新平台证书的RSA配置
+	// 一个商户号只能初始化一个配置,否则会因为重复的下载任务报错
+	private static Config configDongke;
+	private static Config configQinggu;
+	private Config getConfigDongke() {
+		return Objects.nonNull(configDongke) ? configDongke : (configDongke = new RSAAutoCertificateConfig.Builder()
+				.merchantId(mchidDongke).privateKeyFromPath(keyPathDongke).merchantSerialNumber("").apiV3Key("").build());
+	}
+	private Config getConfigQinggu() {
+		return Objects.nonNull(configQinggu) ? configQinggu : (configQinggu = new RSAAutoCertificateConfig.Builder()
+				.merchantId(mchidQinggu).privateKeyFromPath(keyPathQinggu)
+				.merchantSerialNumber("29ADADF7298C9CB7FB38EC837E8F3C4A0C07EFEF")
+				.apiV3Key("POIUYTREWQAS1q2w3e4r5t6y7u8i9o0p").build());
+	}
+	
+	
+	/**
+	 * Native支付 栋科
+	 * @return
+	 * @throws Exception 
+	 */
+	public String pcDongke(String appid, String paynum, int money, String body) throws Exception {
+		return this.pc(this.getConfigDongke(), appid, mchidDongke, paynum, money, body);
+	}
+	
+	/**
+	 * Native支付 青谷
+	 * @return
+	 * @throws Exception 
+	 */
+	public String pcQinggu(String appid, String paynum, int money, String body) throws Exception {
+		return this.pc(this.getConfigQinggu(), appid, mchidQinggu, paynum, money, body);
+	}
+	
+	/**
+	 * Native支付是指商户系统按微信支付协议生成支付二维码,用户再用微信“扫一扫”完成支付的模式。
+	 * Native支付适用于PC网站、实体店单品或订单、媒体广告支付等场景
+	 * @return 返回用于生成二维码的url
+	 * @throws Exception 
+	 */
+	private String pc(Config config, String appid, String mchid, String paynum, int money, String body) throws Exception {
+		com.wechat.pay.java.service.payments.nativepay.NativePayService service = new com.wechat.pay.java.service.payments.nativepay.NativePayService.Builder().config(config).build();
+        com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest request = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
+        com.wechat.pay.java.service.payments.nativepay.model.Amount amount = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
+        amount.setTotal(money); // 订单总金额,单位为分
+        request.setAmount(amount);
+        request.setAppid(appid);
+        request.setMchid(mchid);
+        request.setDescription(body);
+        request.setOutTradeNo(paynum);
+        request.setNotifyUrl(domain+"/wxpay/notify");
+        try {
+        	logger.debug("微信Native支付下单请求参数: {}", JsonUtil.toJson(request));
+        	com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse response = service.prepay(request);
+        	logger.debug("微信Native支付下单返回结果: {}", JsonUtil.toJson(response));
+        	return response.getCodeUrl();
+		} catch (Exception exception) {
+			logger.error("微信Native支付下单请求异常", exception);
+		}
+        return null;
+	}
+
+	
+	/**
+	 * App支付 栋科
+	 * @return
+	 * @throws Exception 
+	 */
+	public ApiPayWxAppResponseVo appDongke(String appid, String paynum, int money, String body) throws Exception {
+		return this.app(this.getConfigDongke(), appid, mchidDongke, paynum, money, body);
+	}
+	
+	/**
+	 * App支付 青谷
+	 * @return
+	 * @throws Exception 
+	 */
+	public ApiPayWxAppResponseVo appQinggu(String appid, String paynum, int money, String body) throws Exception {
+		return this.app(this.getConfigQinggu(), appid, mchidQinggu, paynum, money, body);
+	}
+	
+	/**
+	 * App支付是指商户通过在移动端应用App中集成开放SDK调起微信支付模块来完成支付。目前微信支付支持手机系统有:IOS(苹果)、Android(安卓)和WP(Windows Phone)。
+	 * @return
+	 */
+	private ApiPayWxAppResponseVo app(Config config, String appid, String mchid, String paynum, int money, String body) {
+		com.wechat.pay.java.service.payments.app.AppServiceExtension service = new com.wechat.pay.java.service.payments.app.AppServiceExtension.Builder().config(config).build();
+		com.wechat.pay.java.service.payments.app.model.PrepayRequest request = new com.wechat.pay.java.service.payments.app.model.PrepayRequest();
+		com.wechat.pay.java.service.payments.app.model.Amount amount = new com.wechat.pay.java.service.payments.app.model.Amount();
+        amount.setTotal(money); // 订单总金额,单位为分
+        request.setAmount(amount);
+        request.setAppid(appid);
+        request.setMchid(mchid);
+        request.setDescription(body);
+        request.setOutTradeNo(paynum);
+        request.setNotifyUrl(domain+"/wxpay/notify");
+        try {
+        	logger.debug("微信APP支付下单请求参数: {}", JsonUtil.toJson(request));
+        	com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
+        	logger.debug("微信APP支付下单返回结果: {}", JsonUtil.toJson(response));
+        	ApiPayWxAppResponseVo vo = BeanUtil.transformBean(response, ApiPayWxAppResponseVo.class);
+        	vo.setMchid(mchid);
+        	return vo;
+		} catch (Exception exception) {
+			logger.error("微信APP支付下单请求异常", exception);
+		}
+        return null;
+	}
+
+	
+	/**
+	 * JSAPI支付 栋科
+	 * @return
+	 * @throws Exception 
+	 */
+	public ApiPayWxJsApiResponseVo jsapiDongke(String appid, String paynum, int money, String body) throws Exception {
+		return this.jsapi(this.getConfigDongke(), appid, mchidDongke, paynum, money, body);
+	}
+	
+	/**
+	 * JSAPI支付 青谷
+	 * @return
+	 * @throws Exception 
+	 */
+	public ApiPayWxJsApiResponseVo jsapiQinggu(String appid, String paynum, int money, String body) throws Exception {
+		return this.jsapi(this.getConfigQinggu(), appid, mchidQinggu, paynum, money, body);
+	}
+	
+	/**
+	 * JSAPI支付是指商户通过调用微信支付提供的JSAPI接口,在支付场景中调起微信支付模块完成收款。
+	 * @return
+	 */
+	private ApiPayWxJsApiResponseVo jsapi(Config config, String appid, String mchid, String paynum, int money, String body) {
+		com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension service = new com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension.Builder().config(config).build();
+		com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest request = new com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest();
+		com.wechat.pay.java.service.payments.jsapi.model.Amount amount = new com.wechat.pay.java.service.payments.jsapi.model.Amount();
+        amount.setTotal(money); // 订单总金额,单位为分
+        request.setAmount(amount);
+        request.setAppid(appid);
+        request.setMchid(mchid);
+        request.setDescription(body);
+        request.setOutTradeNo(paynum);
+        request.setNotifyUrl(domain+"/wxpay/notify");
+        try {
+        	logger.debug("微信JSAPI支付下单请求参数: {}", JsonUtil.toJson(request));
+        	com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
+        	logger.debug("微信JSAPI支付下单返回结果: {}", JsonUtil.toJson(response));
+        	ApiPayWxJsApiResponseVo vo = BeanUtil.transformBean(response, ApiPayWxJsApiResponseVo.class);
+        	vo.setMchid(mchid);
+        	return vo;
+		} catch (Exception exception) {
+			logger.error("微信JSAPI支付下单请求异常", exception);
+		}
+        return null;
+	}
+
+	
+	/**
+	 * 订单查询 栋科
+	 * @return
+	 * @throws Exception 
+	 */
+	public boolean queryDongke(String appid, String paynum, int money, String body) throws Exception {
+		return this.query(this.getConfigDongke(), mchidDongke, paynum);
+	}
+	
+	/**
+	 * 订单查询 青谷
+	 * @return
+	 * @throws Exception 
+	 */
+	public boolean queryQinggu(String appid, String paynum, int money, String body) throws Exception {
+		return this.query(this.getConfigQinggu(), mchidQinggu, paynum);
+	}
+	
+	/**
+	 * 商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑
+	 * @return
+	 * @throws Exception
+	 */
+	public boolean query(Config config, String mchid, String paynum) throws Exception {
+		com.wechat.pay.java.service.payments.nativepay.NativePayService service = new com.wechat.pay.java.service.payments.nativepay.NativePayService.Builder().config(config).build();
+		com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest request = new com.wechat.pay.java.service.payments.nativepay.model.QueryOrderByOutTradeNoRequest();
+		request.setMchid(mchid);
+		request.setOutTradeNo(paynum);
+		try {
+			logger.debug("微信订单查询api请求参数: {}", JsonUtil.toJson(request));
+			com.wechat.pay.java.service.payments.model.Transaction transaction = service.queryOrderByOutTradeNo(request);
+        	logger.debug("微信订单查询api返回结果: {}", JsonUtil.toJson(transaction));
+			return transaction.getTradeState() == com.wechat.pay.java.service.payments.model.Transaction.TradeStateEnum.SUCCESS;
+		} catch (Exception exception) {
+			logger.error("微信订单查询api请求异常", exception);
+		}
+		return false;
+	}
+	
+}

+ 24 - 0
src/main/java/com/llisoft/pay/vo/ApiInfoRequestVo.java

@@ -0,0 +1,24 @@
+package com.llisoft.pay.vo;
+
+import javax.validation.constraints.NotBlank;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("支付详情请求实体")
+public class ApiInfoRequestVo {
+
+	@ApiModelProperty("支付号")
+	@NotBlank(message="支付号不能为空")
+    private String pid;
+
+	
+	public String getPid() {
+		return pid;
+	}
+
+	public void setPid(String pid) {
+		this.pid = pid;
+	}
+
+}

+ 42 - 0
src/main/java/com/llisoft/pay/vo/ApiInfoResponseVo.java

@@ -0,0 +1,42 @@
+package com.llisoft.pay.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("支付详情返回实体")
+public class ApiInfoResponseVo {
+
+	@ApiModelProperty("支付号")
+    private String pid;
+
+	@ApiModelProperty("支付金额(分)")
+    private int money;
+	
+	@ApiModelProperty("是否已支付")
+	private boolean payed;
+
+	public String getPid() {
+		return pid;
+	}
+
+	public void setPid(String pid) {
+		this.pid = pid;
+	}
+
+	public int getMoney() {
+		return money;
+	}
+
+	public void setMoney(int money) {
+		this.money = money;
+	}
+
+	public boolean getPayed() {
+		return payed;
+	}
+
+	public void setPayed(boolean payed) {
+		this.payed = payed;
+	}
+  
+}

+ 20 - 0
src/main/java/com/llisoft/pay/vo/ApiPayAliAppResponseVo.java

@@ -0,0 +1,20 @@
+package com.llisoft.pay.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("支付宝返回实体 APP")
+public class ApiPayAliAppResponseVo {
+
+	@ApiModelProperty("支付号")
+    private String pid;
+	
+	public String getPid() {
+		return pid;
+	}
+
+	public void setPid(String pid) {
+		this.pid = pid;
+	}
+  
+}

+ 37 - 0
src/main/java/com/llisoft/pay/vo/ApiPayRequestVo.java

@@ -0,0 +1,37 @@
+package com.llisoft.pay.vo;
+
+import javax.validation.constraints.NotBlank;
+
+import org.hibernate.validator.constraints.Range;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("支付请求实体")
+public class ApiPayRequestVo {
+
+	@ApiModelProperty("支付金额(单位:分)")
+	@Range(min=1, message="支付金额")
+	private int money;
+	
+	@ApiModelProperty("商品标题,第三方支付页面显示")
+	@NotBlank(message="商品标题不能为空")
+    private String title;
+
+	public int getMoney() {
+		return money;
+	}
+
+	public void setMoney(int money) {
+		this.money = money;
+	}
+
+	public String getTitle() {
+		return title;
+	}
+
+	public void setTitle(String title) {
+		this.title = title;
+	}
+
+}

+ 31 - 0
src/main/java/com/llisoft/pay/vo/ApiPayWxAppResponseVo.java

@@ -0,0 +1,31 @@
+package com.llisoft.pay.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("微信支付返回实体 APP")
+public class ApiPayWxAppResponseVo extends com.wechat.pay.java.service.payments.jsapi.model.PrepayWithRequestPaymentResponse{
+
+	@ApiModelProperty("支付号")
+    private String pid;
+	
+	@ApiModelProperty("商户号")
+	private String mchid;
+
+	public String getPid() {
+		return pid;
+	}
+
+	public void setPid(String pid) {
+		this.pid = pid;
+	}
+
+	public String getMchid() {
+		return mchid;
+	}
+
+	public void setMchid(String mchid) {
+		this.mchid = mchid;
+	}
+  
+}

+ 31 - 0
src/main/java/com/llisoft/pay/vo/ApiPayWxJsApiResponseVo.java

@@ -0,0 +1,31 @@
+package com.llisoft.pay.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("微信支付返回实体 APP")
+public class ApiPayWxJsApiResponseVo extends com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse{
+
+	@ApiModelProperty("支付号")
+    private String pid;
+	
+	@ApiModelProperty("商户号")
+	private String mchid;
+
+	public String getPid() {
+		return pid;
+	}
+
+	public void setPid(String pid) {
+		this.pid = pid;
+	}
+
+	public String getMchid() {
+		return mchid;
+	}
+
+	public void setMchid(String mchid) {
+		this.mchid = mchid;
+	}
+  
+}

+ 31 - 0
src/main/java/com/llisoft/pay/vo/ApiPayWxNativeResponseVo.java

@@ -0,0 +1,31 @@
+package com.llisoft.pay.vo;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("微信支付返回实体 Native")
+public class ApiPayWxNativeResponseVo {
+
+	@ApiModelProperty("支付号")
+    private String pid;
+	
+	@ApiModelProperty("用于生成二维码的字符")
+	private String codes;
+
+	public String getPid() {
+		return pid;
+	}
+
+	public void setPid(String pid) {
+		this.pid = pid;
+	}
+
+	public String getCodes() {
+		return codes;
+	}
+
+	public void setCodes(String codes) {
+		this.codes = codes;
+	}
+  
+}

+ 1 - 0
src/main/java/com/llisoft/pay/vo/OrderAddRequestVo.java

@@ -8,6 +8,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
 @ApiModel("订单添加请求实体")
+@Deprecated
 public class OrderAddRequestVo {
 
 	@ApiModelProperty("appKey")

+ 1 - 0
src/main/java/com/llisoft/pay/vo/OrderPayRequestVo.java

@@ -8,6 +8,7 @@ import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
 @ApiModel("订单支付请求实体")
+@Deprecated
 public class OrderPayRequestVo {
 
 	@ApiModelProperty("订单号")

+ 124 - 0
src/main/java/com/llisoft/pay/vo/ResponseVo.java

@@ -0,0 +1,124 @@
+package com.llisoft.pay.vo;
+
+import com.llisoft.pay.common.CodeEnum;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+@ApiModel("公共返回实体")
+public class ResponseVo<T> {
+
+	@ApiModelProperty(value="代码", required=true)
+	private int code;
+	@ApiModelProperty(value="信息", required=true)
+	private String msg; 
+	@ApiModelProperty("数据")
+    private T data;
+
+    
+    /**
+     * 默认成功方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> success(T data){
+    	return ResponseVo.build(data, CodeEnum.SUCCESS); 
+    }
+
+    /**
+     * 默认成功方法
+     * @param data
+     * @return 
+     * @return
+     */
+    public static <T> ResponseVo<T> success(T data, String msg){
+    	return ResponseVo.build(data, CodeEnum.SUCCESS.getCode(), msg); 
+    }
+    
+    /**
+     * 默认失败方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> fail(T data){
+    	return ResponseVo.build(data, CodeEnum.FAIL); 
+    }
+    
+    /**
+     * 默认失败方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> fail(String msg){
+    	return ResponseVo.build(null, CodeEnum.FAIL.getCode(), msg); 
+    }
+    
+    /**
+     * 默认失败方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> fail(T data, String msg){
+    	return ResponseVo.build(data, CodeEnum.FAIL.getCode(), msg); 
+    }
+	
+    /**
+     * 默认构建方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> build(CodeEnum codeEnum){
+    	return ResponseVo.build(null, codeEnum); 
+    }
+    
+    /**
+     * 默认构建方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> build(T data, CodeEnum codeEnum){
+    	return ResponseVo.build(data, codeEnum.getCode(), codeEnum.getMsg()); 
+    }
+    
+    /**
+     * 默认构建方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> build(int code, String msg){
+    	return build(null, code, msg); 
+    }
+    
+    /**
+     * 默认构建方法
+     * @param data
+     * @return
+     */
+    public static <T> ResponseVo<T> build(T data, int code, String msg){
+    	ResponseVo<T> responseBean = new ResponseVo<>();
+    	responseBean.setCode(code);
+    	responseBean.setMsg(msg);
+    	responseBean.setData(data);
+    	return responseBean; 
+    }
+    
+	public int getCode() {
+		return code;
+	}
+	public void setCode(int code) {
+		this.code = code;
+	}
+	public String getMsg() {
+		return msg;
+	}
+	public void setMsg(String msg) {
+		this.msg = msg;
+	}
+	public T getData() {
+		return data;
+	}
+	public void setData(T data) {
+		this.data = data;
+	}
+
+}

+ 3 - 0
src/main/resources/application.yml

@@ -16,6 +16,9 @@ wxpay: #微信支付
   mchkey: 1q2w3e4r5t6y7u8i9o0pPOIUYTREWQAS
   appid: wxc61229f2ac6c068d
   secret: 559eb6029da80950634a43f55dc453bd
+  ##以下为微信支付v3配置
+  keyPathDongke: #商户API私钥路径 栋科
+  keyPathQinggu: #商户API私钥路径 青谷
   
 ##数据源配置
 spring.datasource: 

+ 2 - 2
src/test/java/com/llisoft/pay/ServiceTest.java

@@ -6,7 +6,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
-import com.llisoft.pay.service.WxPayService;
+import com.llisoft.pay.service.PayWxService;
 import com.llisoft.pay.util.CodeUtil;
 
 @SpringBootTest
@@ -14,7 +14,7 @@ import com.llisoft.pay.util.CodeUtil;
 public class ServiceTest {
 	
 	@Autowired
-	WxPayService wxPayService;
+	PayWxService wxPayService;
 	
 	@Test
 	public void test() throws Exception{