如果有幸能看到,其实只为自己记录,回头复习用
6、只为自己整理,大概的过了一边,在Service层哪里还需好好理解。。
首先看下支付的一些相关知识点
(1)、支付方案:
(2)、支付流程:
一般流程说明: 原作者
在这提一点,由于网络原因等异常情况支付平台可能出现多次发送支付结果的情况,通知回调接口商户要注意做好接口幂等,其余的不再多说。
在线支付过程:
04)当用户请求来了,你得获取客户的相关信息,例如:订单号,金额,支付银行等14个信息
注意:其中hmac是由客户订单信息和商家密钥生成,通过易宝提供的工具包自动生成
06)易宝如果验成功,即客户发送过来的信息与易宝生成的信息相同的话,易宝认为是合法用户请求,否则非法用户请求
注意:验证是否成功,主要通过hmac和密钥作用
07)如果是合法用户的支付请求的话,易宝再将请求转发到客户指定的银行,例如:招商银行
注意:易宝必须支持招商银行在线支付
11)商家网站可以用GET方式接收易宝的响应数据,经过验证合法后,再将付款结果,显示在用户的浏览器
注意:验证是否成功,主要通过hmac和密钥作用
首先来看BaseController
public class BaseController {
private Logger logger = LoggerFactory.getLogger(BaseController.class);
/**
* 获取用户ID,用户ID可能为NULL,需自行判断
*/
protected Long getUserId(HttpServletRequest request) {
String sId = request.getHeader("userId");
if (!StringUtil.isEmpty(sId)) {
try {
Long userId = Long.parseLong(sId);
return userId;
} catch (NumberFormatException e) {
logger.warn("请求头userId参数格式错误:{}", sId);
}
}
return null;
}
/**
* 获取用户ID,当userId为空的时候抛出异常
*/
protected Long getNotNullUserId(HttpServletRequest request) throws BusinessException {
Long userId = getUserId(request);
if (userId == null) {
throw new BusinessException("用户ID不能为空");
}
return userId;
}
/**
* 获取请求来源类型
*/
protected RequestFrom getRequestFrom(HttpServletRequest request) throws BusinessException {
String from = request.getHeader("from");
if (StringUtil.isEmpty(from)) {
throw new BusinessException("请求头错误未包含来源字段");
}
try {
int iFom = Integer.parseInt(from);
return RequestFrom.getById(iFom);
} catch (NumberFormatException e) {
throw new BusinessException("请求头来源字段类型错误");
}
}
/**
* 获取移动端请求头信息
*/
protected MobileInfo getMobileInfo(HttpServletRequest request) throws BusinessException {
String appVersion = request.getHeader("appVersion");
String systemVersion = request.getHeader("appSystemVersion");
String deviceId = request.getHeader("appDeviceId");
Integer width = null;
Integer height = null;
int night = 0;
try {
width = Integer.parseInt(request.getHeader("appDeviceWidth"));
height = Integer.parseInt(request.getHeader("appDeviceHeight"));
if (request.getHeader("nightMode") != null) {
night = Integer.parseInt(request.getHeader("nightMode"));
}
} catch (NumberFormatException e) {
throw new BusinessException("移动端请求头不符合约定");
}
if (StringUtil.isEmpty(appVersion) || width == null || height == null) {
throw new BusinessException("移动端请求头不符合约定");
}
return new MobileInfo(appVersion, systemVersion, deviceId, width, height, night != 0);
}
}
控制层异常统一处理
/**
* 控制层异常统一处理
*/
public class RestErrorHandler {
private static Logger logger = LoggerFactory.getLogger(RestErrorHandler.class);
@ExceptionHandler(BindException.class)
@ResponseBody
public AjaxResult handleBindException(BindException exception) {
AjaxResult result = AjaxResult.getError(ResultCode.ParamException);
Set
for (FieldError er : exception.getFieldErrors()) {
errors.add(new ValidationError(er.getObjectName(), er.getField(), er.getDefaultMessage()));
}
result.setData(errors);
logger.warn("参数绑定错误:{}", exception.getObjectName());
return result;
}
@ExceptionHandler(BusinessException.class)
@ResponseBody
public AjaxResult handleBusinessException(BusinessException exception) {
AjaxResult result = AjaxResult.getError(ResultCode.BusinessException);
result.setMessage(exception.getMessage());
logger.warn("业务错误:{}", exception.getMessage());
return result;
}
@ExceptionHandler(SystemException.class)
@ResponseBody
public AjaxResult handleSystemException(SystemException exception) {
AjaxResult result = AjaxResult.getError(ResultCode.SystemException);
result.setMessage("系统错误");
logger.error("系统错误:{}", exception);
return result;
}
@ExceptionHandler(DBException.class)
@ResponseBody
public AjaxResult handleDBException(DBException exception) {
AjaxResult result = AjaxResult.getError(ResultCode.DBException);
result.setMessage("数据库错误");
logger.error("数据库错误:{}", exception);
return result;
}
@ExceptionHandler(Exception.class)
@ResponseBody
public AjaxResult handleException(Exception exception) {
AjaxResult result = AjaxResult.getError(ResultCode.UnknownException);
result.setMessage("服务器错误");
logger.error("服务器错误:{}", exception);
return result;
}
}
支付通知入口:
/**
* 支付通知入口
* Created by Martin on 2016/7/01.
*/
@RequestMapping(value = "/open/payNotify")
public class PayNotifyController extends BaseController {
private static Logger logger = LoggerFactory.getLogger(PayNotifyController.class);
/**
* 国内支付宝app通知回调
* @param request
* @param response
* @throws SystemException
* @throws BusinessException
*/
@RequestMapping(value = "/alipayNotifyMainApp", method = RequestMethod.POST)
public void alipayNotifyMainApp(HttpServletRequest request, HttpServletResponse response) throws SystemException, BusinessException {
alipayNotifyService.alipayNotifyMainApp(request, response);
}
/**
* 国内支付宝web通知回调
* @param request
* @param response
* @throws SystemException
* @throws BusinessException
*/
@RequestMapping(value = "/alipayNotifyMain", method = RequestMethod.POST)
public void alipayNotifyMain(HttpServletRequest request, HttpServletResponse response) throws SystemException, BusinessException {
alipayNotifyService.alipayNotifyMain(request, response);
}
/**
* 国际支付宝app通知回调
* @param request
* @param response
* @throws SystemException
* @throws BusinessException
*/
@RequestMapping(value = "alipayNotifyGlobalApp", method = RequestMethod.POST)
public void alipayNotifyGlobalApp(HttpServletRequest request, HttpServletResponse response) throws SystemException, BusinessException {
alipayNotifyService.alipayNotifyGlobalApp(request, response);
}
}
支付请求相关接口
/**
* 支付请求相关接口
*/
@Controller
@RequestMapping("/app/payRequest")
public class PayRequestController extends BaseController {
private static Logger logger = LoggerFactory.getLogger(PayRequestController.class);
@Autowired
private IPayRouteService payRouteService;
/**
* 组装支付请求报文
* @param payRequestParam
* @return
* @throws BusinessException
* @throws SystemException
*/
@ResponseBody
@RequestMapping(value = "/getPayParams", method = RequestMethod.POST)
public AjaxResult getPayParams(@RequestBody PayRequestParam payRequestParam) throws BusinessException, SystemException {
return AjaxResult.getOK(payRouteService.getPayRetMap(payRequestParam));
}
}
接下来在看看配置文件,支付相关的暂时省略,因为俺没有。
userId="${master1.jdbc.username}"
password="${master1.jdbc.password}">
#MySQL
mysql.jdbc.url=jdbc:mysql://127.0.0.1:3306/sps_db?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true
mysql.jdbc.username=root
#连接数据库的密码.
mysql.jdbc.password=root
mysql.jdbc.initialSize=10
#连接池在空闲时刻保持的最大连接数.
mysql.jdbc.minIdle=10
#连接池在同一时刻内所提供的最大活动连接数。
mysql.jdbc.maxActive=100
#当发生异常时数据库等待的最大毫秒数 (当没有可用的连接时).
mysql.jdbc.maxWait=60000
mysql.jdbc.timeBetweenEvictiOnRunsMillis=60000
mysql.jdbc.minEvictableIdleTimeMillis=300000
mysql.jdbc.removeAbandOnedTimeout=7200
mysql.jdbc.validatiOnQuery=SELECT 'x'
mysql.jdbc.testWhileIdle=true
mysql.jdbc.testOnBorrow=false
mysql.jdbc.testOnReturn=false
mysql.jdbc.filters=slf4j
mysql.jdbc.removeAbandOned=true
mysql.jdbc.logAbandOned=true
#Redis
redis.ip=127.0.0.1
redis.port=6379
redis.timeout=6000
#Redis-pool
redis.pool.maxTotal=10000
redis.pool.maxIdle=1000
redis.pool.testOnBorrow=true
#RabbitMQ
rabbitmq.master.ip=127.0.0.1
rabbitmq.master.port=5672
rabbitmq.master.username=guest
rabbitmq.master.password=guest
接着再看这几个
xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.0.xsd">
xmlns:cOntext="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd ">
xmlns:util="http://www.springframework.org/schema/util"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd
">
/=anon
/index.jsp=anon
/app/**=stateless
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd http://www.springframework.org/schema/rabbit http://www.springframework.org/schema/rabbit/spring-rabbit.xsd">
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
ch.qos.logback.classic.helpers.MDCInsertingServletFilter
这只是简单的过来一遍,对大概的流程有个印象。需要配置文件的时候能找到。如果你有幸能看到这段话,那就好好加油吧。gogogo。