热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Java后端支付大杂烩之sps.controller(支付请求入口,配置文件)(五)

7、sps.controller.base,front.说明如果有幸能看到,其实只为自己记录,回头复习用1、本文项目来自Martin404,自己只是临摹大佬的项目。2、重要的是学习

7、sps.controller.base,front.

说明

如果有幸能看到,其实只为自己记录,回头复习用

  • 1、本文项目来自Martin404,自己只是临摹大佬的项目。
  • 2、重要的是学习过程,而不是结果。但,结果同样重要,加油。gogogo。
  • 3、框架搭建就略过了。配置文件太多。遇到的时候贴出来。也收藏起来,留着备用。
  • 4、Gist、Insight.io for GitHub必备吧,划词翻译不懂的单词划一划。
  • 5、代码提交到这里了GitHub。根据提交记录找自己想要的类库。
  • 6、只为自己整理,大概的过了一边,在Service层哪里还需好好理解。。

    目录

    • 2、core.dao,service,web(重点是接口的设计)点这里
    • 3、sps包~dto、enums、mq点这里
    • 4、在Dao层定义了domian、mapper映射文件,想了解的可以去看看。有助于理解整个系统。点这里
    • 5、pay.util.app。 pay.stratege,支付工具类,和支付策略点这里
    • 6、sps.service及实现类(重点)点这里

首先看下支付的一些相关知识点

(1)、支付方案:

(2)、支付流程:

《Java后端支付大杂烩之sps.controller(支付请求入口,配置文件)(五)》

一般流程说明: 原作者

  • 用户在商户网站选定商品并下单,在商户支付页面选择对应支付平台图标,进行支付;
  • 商户按照文档提交支付请求接口组织报文,向支付平台发送支付请求;
  • 如果是PC端,会跳转到对应支付平台的支付页面,如果是移动端,会唤起对应的支付工具,用户在支付平台输入支付信息,提交支付;
  • 支付平台将支付结果通知商户;
  • 若支付成功,则支付平台将交易结果异步发送给商户;
  • 商户若未收到交易结果,则商户按照文档查询接口向支付平台发请求查询该交易,以确定消费交易的状态,支付平台收到 查询请求时,将同步返回该笔消费交易的交易结果;
  • 商户若收到交易结果,如果未向支付平台反馈已收到交易结果,支付平台会重复发送交易结果。

在这提一点,由于网络原因等异常情况支付平台可能出现多次发送支付结果的情况,通知回调接口商户要注意做好接口幂等,其余的不再多说。

在线支付过程:

  • 01)创建合法的商业购物网站,且在易宝支付平台申请成为商家,并提供商家银行卡号,等待审查
  • 02)如果审查通过,和易宝支付签约,得向易宝支付一定的接口使用费或每笔交易的手续费,通常是交易额的1%左右
  • 03)付款后,易宝会给每个商家一个唯一的商家编号,密钥,和接口文档和jar包
  • 04)当用户请求来了,你得获取客户的相关信息,例如:订单号,金额,支付银行等14个信息

    注意:其中hmac是由客户订单信息和商家密钥生成,通过易宝提供的工具包自动生成

  • 05)用表单的方式,以POST或GET请求,使用GBK或GB2312向易宝发出支付请求,请求中带有14个参数
  • 06)易宝如果验成功,即客户发送过来的信息与易宝生成的信息相同的话,易宝认为是合法用户请求,否则非法用户请求

    注意:验证是否成功,主要通过hmac和密钥作用

  • 07)如果是合法用户的支付请求的话,易宝再将请求转发到客户指定的银行,例如:招商银行

    注意:易宝必须支持招商银行在线支付

  • 08)凡是转账,查询,等等都由银行后台操作完成,是全封闭的,与易宝没有任何关系,千万不要认为是易宝在处理资金结算
  • 09)银行处理完毕后,将响应结果转发到易宝在线支付平台
  • 10)易宝在线支付经过加工处理后,再将结果响应到用户指定的外网可以访问的Servlet或Jsp页面
  • 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 errors = new HashSet();
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));
}
}

接下来在看看配置文件,支付相关的暂时省略,因为俺没有。

《Java后端支付大杂烩之sps.controller(支付请求入口,配置文件)(五)》

generatorConfig





















cOnnectionURL="${master1.jdbc.url}"
userId="${master1.jdbc.username}"
password="${master1.jdbc.password}">






type="XMLMAPPER"/>


数据库配置:

#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

接着再看这几个

《Java后端支付大杂烩之sps.controller(支付请求入口,配置文件)(五)》

 applicationContext:


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cOntext="http://www.springframework.org/schema/context"
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">

expression="org.springframework.stereotype.Controller" />


class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">


classpath:server_config.properties
classpath:sys_config.properties



















class="org.springframework.data.redis.serializer.StringRedisSerializer" />
class="org.springframework.data.redis.serializer.JdkSerializationRedisSerializer" />




































${shiro.guest.username}





































mybatis_config



























value="pageNum=start;pageSize=limit;pageSizeZero=zero;reasOnable=heli;count=contsql"/>























spring_mvc


xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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 ">







class="org.springframework.web.multipart.commons.CommonsMultipartResolver">





class="org.springframework.web.servlet.view.InternalResourceViewResolver">



depends-on="lifecycleBeanPostProcessor">







spring_shiro


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
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






Spring-rabbitmq


xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:rabbit="http://www.springframework.org/schema/rabbit"
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">

username="${rabbitmq.master.username}" password="${rabbitmq.master.password}"/>

exchange="order_topic_exchange" message-cOnverter="gsonConverter"/>






















web.xml


xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
Pay Map Service

webAppRootKey
PayMap



contextConfigLocation
classpath:applicationContext.xml,classpath:spring_shiro.xml,classpath:spring_rabbitmq.xml




MDCInsertingServletFilter

ch.qos.logback.classic.helpers.MDCInsertingServletFilter



MDCInsertingServletFilter
/*



shiroFilter
org.springframework.web.filter.DelegatingFilterProxy


shiroFilter
/*


字符集过滤器
encodingFilter
org.springframework.web.filter.CharacterEncodingFilter

字符集编码
encoding
UTF-8



encodingFilter
/*


DruidWebStatFilter
com.alibaba.druid.support.http.WebStatFilter

exclusions
*.js,*.gif,*.jpg,*.png,*.css,*.ico,/druid/*



DruidWebStatFilter
/*


loggingFilter
com.guo.core.web.system.filters.LoggingFilter


loggingFilter
/*


spring监听器
org.springframework.web.context.ContextLoaderListener


Introspector缓存清除监听器
org.springframework.web.util.IntrospectorCleanupListener


request监听器
org.springframework.web.context.request.RequestContextListener

c
系统初始化监听器
com.guo.core.web.system.listener.InitListener


default
/static/*


spring mvc servlet
springMvc
org.springframework.web.servlet.DispatcherServlet

spring mvc 配置文件
contextConfigLocation
classpath:spring_mvc.xml

1


springMvc
/


DruidStatView
com.alibaba.druid.support.http.StatViewServlet


DruidStatView
/druid/*


HiddenHttpMethodFilter
org.springframework.web.filter.HiddenHttpMethodFilter


HiddenHttpMethodFilter
springMvc



30


index.jsp


这只是简单的过来一遍,对大概的流程有个印象。需要配置文件的时候能找到。如果你有幸能看到这段话,那就好好加油吧。gogogo。


推荐阅读
  • Maven + Spring + MyBatis + MySQL 环境搭建与实例解析
    本文详细介绍如何使用MySQL数据库进行环境搭建,包括创建数据库表并插入示例数据。随后,逐步指导如何配置Maven项目,整合Spring框架与MyBatis,实现高效的数据访问。 ... [详细]
  • Spring Security基础配置详解
    本文详细介绍了Spring Security的基础配置方法,包括如何搭建Maven多模块工程以及具体的安全配置步骤,帮助开发者更好地理解和应用这一强大的安全框架。 ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
  • spring boot使用jetty无法启动 ... [详细]
  • flea,frame,db,使用,之 ... [详细]
  • Flutter 核心技术与混合开发模式深入解析
    本文深入探讨了 Flutter 的核心技术,特别是其混合开发模式,包括统一管理模式和三端分离模式,以及混合栈原理。通过对比不同模式的优缺点,帮助开发者选择最适合项目的混合开发策略。 ... [详细]
  • 在尝试启动Java应用服务器Tomcat时,遇到了org.apache.catalina.LifecycleException异常。本文详细记录了异常的具体表现形式,并提供了有效的解决方案。 ... [详细]
  • Excel技巧:单元格中显示公式而非结果的解决方法
    本文探讨了在Excel中如何通过简单的方法解决单元格显示公式而非计算结果的问题,包括使用快捷键和调整单元格格式两种方法。 ... [详细]
  • Go语言实现文件读取与终端输出
    本文介绍如何使用Go语言编写程序,通过命令行参数指定文件路径,读取文件内容并将其输出到控制台。代码示例中包含了错误处理和资源管理的最佳实践。 ... [详细]
  • 本文介绍了如何在C# WinForms应用程序中通过自定义绘制实现圆形按钮的方法,适合初学者参考。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • Beetl是一款先进的Java模板引擎,以其丰富的功能、直观的语法、卓越的性能和易于维护的特点著称。它不仅适用于高响应需求的大型网站,也适合功能复杂的CMS管理系统,提供了一种全新的模板开发体验。 ... [详细]
  • 一、Advice执行顺序二、Advice在同一个Aspect中三、Advice在不同的Aspect中一、Advice执行顺序如果多个Advice和同一个JointPoint连接& ... [详细]
  • 本文总结了一次针对大厂Java研发岗位的面试经历,探讨了面试中常见的问题及其背后的原因,并分享了一些实用的面试准备资料。 ... [详细]
  • 在尝试通过自定义端口部署Spring Cloud Eureka时遇到了连接失败的问题。本文详细描述了问题的现象,并提供了有效的解决方案,以帮助遇到类似情况的开发者。 ... [详细]
author-avatar
半路张三_711
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有