近来,欲将三方付出途径对接入笔者框架内,简化,后期事务功用的开发。
为满意此功用的可扩展性,欲界说“订单事务接口”、“付出办法接口”规则。
当,用户下单时,依据传入的“事务类型”获取详细的事务完结,依据“付出办法”获取详细的下单数据。
如此,即可在详细的事务代码中,完结对应的事务功用。
开发之始,即为规划,此篇仅为根底规划篇,后期将会逐渐完善各三方途径付出完结类。
烦琐至此,此下,正式开文。
思路规划图如下
此下,规划详细的表结构,笔者依据现在主意,规划两张表“订单表”、“订单进程表”。
数据库表结构如下
表联系图如下
既,表规划完结,此下将详细完结事务功用。
开篇之始,笔者先界说对应的“订单相关字典”。
其中“订单事务类型”未预留字典类型,详细事务功用引入此库完结时,自主界说即可。
另,付出办法现在框架仅完结“微信V2JSApi”办法,后期陆续完结,并界说相关字典,此处暂不界说悉数字典。
字典装备类如下
package com.threeox.biz.order.config;
import com.threeox.drivenlibrary.engine.annotation.config.DictionaryConfig;
/**
* 订单字典常量类
*
* @author 赵屈犇
* @version 1.0
* @date 创立时刻: 2022/4/18 22:24
*/
public class OrderDictConstants {
/**
* 订单事务类型
*/
@DictionaryConfig(dictionaryCode = OrderBizType.DICTIONARY_CODE, dictionaryName = "订单事务类型", remark = "订单事务类型", version = 2)
public static class OrderBizType {
public static final String DICTIONARY_CODE = "2008";
}
/**
* 订单状况
*/
@DictionaryConfig(dictionaryCode = OrderStatus.DICTIONARY_CODE, dictionaryName = "订单状况", remark = "订单状况", version = 2)
public static class OrderStatus {
public static final String DICTIONARY_CODE = "2009";
/**
* 已下单
*/
@DictionaryConfig(dictionaryName = "已下单")
public static final String HAVE_ORDER = "200901";
/**
* 付出成功
*/
@DictionaryConfig(dictionaryName = "付出成功")
public static final String PAYMENT_SUCCESS = "200902";
/**
* 付出失败
*/
@DictionaryConfig(dictionaryName = "付出失败")
public static final String PAYMENT_FAILED = "200903";
/**
* 付出金额有误
*/
@DictionaryConfig(dictionaryName = "付出金额有误")
public static final String PAYMENT_AMOUNT_WRONG = "200904";
}
/**
* 付出办法
*/
@DictionaryConfig(dictionaryCode = PayWay.DICTIONARY_CODE, dictionaryName = "付出办法", remark = "付出办法", version = 2)
public static class PayWay {
public static final String DICTIONARY_CODE = "2010";
/**
* 微信JSAPI付出
*/
@DictionaryConfig(dictionaryName = "微信JSAPI_V2付出")
public static final String WX_JS_API_V2 = "201001";
/**
* 微信APP付出
*/
@DictionaryConfig(dictionaryName = "微信APP_V2付出")
public static final String WX_APP_API_V2 = "201002";
}
}
为完结框架高扩展性,笔者欲界说两套接口标准,供详细事务、付出办法完结。
接口标准类
订单事务扩展类
此接口现在暂声明两套接口,“获取事务快照数据”、“处理付出回调”函数,用于详细事务完结。
后期,如需详细完结再增加。
package com.threeox.biz.order.factory.inter;
import com.threeox.biz.order.entity.OrderInfo;
import com.threeox.biz.order.entity.inter.IOrderBizInfo;
import com.threeox.biz.order.entity.inter.IPayNotifyInfo;
import com.threeox.dblibrary.executor.inter.ISqlExecutor;
/**
* 订单接口扩展类
*
* @author 赵屈犇
* @version 1.0
* @date 创立时刻: 2022/4/13 23:43
*/
public interface IOrderExtend<T extends IOrderBizInfo> {
/**
* 获取事务快照数据
*
* @param executor
* @param orderInfo
* @return a
* @throws Exception
* @author 赵屈犇
* @date 创立时刻: 2022/4/18 21:30
* @version 1.0
*/
T getBizSnapshot(ISqlExecutor executor, OrderInfo orderInfo) throws Exception;
/**
* 处理付出回调
*
* @param executor
* @param orderInfo
* @param notifyInfo
* @param currentStatus
* @return a
* @throws Exception
* @author 赵屈犇
* @date 创立时刻: 2022/5/28 23:52
* @version 1.0
*/
void handlePayNotify(ISqlExecutor executor, OrderInfo orderInfo, IPayNotifyInfo notifyInfo, String currentStatus) throws Exception;
}
付出办法接口标准
此接口,现在仅需获取各付出途径获取共同下单数据函数。
package com.threeox.biz.order.factory.inter;
import com.alibaba.fastjson.JSONObject;
import com.threeox.biz.order.entity.OrderInfo;
/**
* 付出接口界说
*
* @author 赵屈犇
* @version 1.0
* @date 创立时刻: 2022/4/12 21:59
*/
public interface IPaymentFactory {
/**
* 共同下单
*
* @param orderInfo
* 订单目标
* @author 赵屈犇
* @return
* @date 2022/4/23 17:45
*/
JSONObject placeOrder(OrderInfo orderInfo) throws Exception;
}
至此,接口标准已界说。
此下,笔者欲完结付出办法根底完结类,供详细事务逻辑承继扩展。
付出办法根底完结类
此根底类,现在仅需依据详细的应用途径获取途径信息,调用对应子类的共同下单完结办法。
package com.threeox.biz.order.factory.impl.base;
import com.alibaba.fastjson.JSONObject;
import com.threeox.biz.order.entity.OrderInfo;
import com.threeox.biz.order.factory.inter.IPaymentFactory;
import com.threeox.drivenlibrary.engine.config.DrivenEngineConfig;
import com.threeox.drivenlibrary.engine.entity.driven.config.OpenPlatformConfigMessage;
import com.threeox.drivenlibrary.enums.ResponseResult;
import com.threeox.drivenlibrary.exception.ResponseException;
/**
* 根底付出工厂
*
* @author 赵屈犇
* @version 1.0
* @date 创立时刻: 2022/4/23 17:37
*/
public abstract class BasePaymentFactory implements IPaymentFactory {
@Override
public JSONObject placeOrder(OrderInfo orderInfo) throws Exception {
OpenPlatformConfigMessage openPlatform = DrivenEngineConfig.getInstance().getOpenPlatform(orderInfo.getAppChannelCode());
if (openPlatform == null) {
throw ResponseException.newInstance(ResponseResult.UN_CONFIG_OPEN_INFO);
}
return placeOrder(orderInfo, openPlatform);
}
/**
* 共同下单完结办法
*
* @param orderInfo
* @param openPlatform
* @author 赵屈犇
* @return
* @date 2022/4/23 17:50
*/
protected abstract JSONObject placeOrder(OrderInfo orderInfo, OpenPlatformConfigMessage openPlatform) throws Exception ;
}
以上至此,已完结详细标准界说。此下将首要完结“下单接口”界说。
共同下单接口完结
此接口,笔者在详细完结之前,依据事务类型,获取了指定的事务完结类,并给订单表中存储了“事务快照数据”,方便后期运维查看。
并在订单信息入库成功后,依据付出办法获取详细的付出完结类,获取下单数据,提供给“调用方”进行付出恳求。
package com.threeox.biz.order.api;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.threeox.biz.order.config.OrderDictConstants;
import com.threeox.biz.order.config.OrderRequestConfig;
import com.threeox.biz.order.entity.OrderInfo;
import com.threeox.biz.order.entity.inter.IOrderBizInfo;
import com.threeox.biz.order.factory.inter.IOrderExtend;
import com.threeox.biz.order.factory.inter.IPaymentFactory;
import com.threeox.drivenlibrary.engine.ExtendFactory;
import com.threeox.drivenlibrary.engine.annotation.api.Api;
import com.threeox.drivenlibrary.engine.annotation.api.ApiVerifyConfig;
import com.threeox.drivenlibrary.engine.config.entity.request.base.RequestMessage;
import com.threeox.drivenlibrary.engine.entity.params.RequestParam;
import com.threeox.drivenlibrary.engine.function.impl.AbstractApiExtend;
import com.threeox.drivenlibrary.engine.request.build.RequestBuilder;
import com.threeox.drivenlibrary.engine.util.RequestUtils;
import com.threeox.utillibrary.date.TimeUtils;
import com.threeox.utillibrary.java.IDGenerate;
import java.util.Date;
/**
* 下单api扩展
*
* @author 赵屈犇
* @version 1.0
* @date 创立时刻: 2022/4/13 22:21
*/
@Api(apiUrl = "placeOrder", apiName = "共同下单", verifyConfigs = {
@ApiVerifyConfig(paramCode = "orderName", emptyHint = "请传入订单名称"),
@ApiVerifyConfig(paramCode = "payWay", emptyHint = "请传入付出办法"),
@ApiVerifyConfig(paramCode = "bizType", emptyHint = "请传入事务类型"),
@ApiVerifyConfig(paramCode = "bizKey", emptyHint = "请传入事务主键")
}, moduleUrl = "pay", requestCodes = {
OrderRequestConfig.SAVE_ORDER_INFO,
OrderRequestConfig.SAVE_ORDER_PROCESS_INFO
})
public class PlaceOrderExtend extends AbstractApiExtend<OrderInfo> {
@Override
public boolean onBeforeApiExecute() throws Exception {
OrderInfo requestParams = getRequestParams();
// 获取事务类型
String bizType = requestParams.getBizType();
// 依据事务类型
IOrderExtend orderExtend = ExtendFactory.getInstance().getOrderExtend(bizType);
if (orderExtend != null) {
IOrderBizInfo bizSnapshot = orderExtend.getBizSnapshot(getSqlExecutor(), requestParams);
if (bizSnapshot != null) {
putRequestParam("bizSnapshot", JSON.toJSONString(bizSnapshot));
requestParams.setBizSnapshot(getParamValue("bizSnapshot"));
}
putRequestParam("payMoney", bizSnapshot.getPayMoney());
requestParams.setPayMoney(bizSnapshot.getPayMoney());
} else {
errorResult("未找到对应付出事务!");
return false;
}
String orderNum = IDGenerate.getOrderNum();
putRequestParam("orderNum", orderNum);
requestParams.setOrderNum(orderNum);
Date nowTimeDate = TimeUtils.getNowTimeDate();
putRequestParam("operateTime", nowTimeDate);
requestParams.setOperateTime(nowTimeDate);
String ipAddress = RequestUtils.getIPAddress(servletRequest());
putRequestParam("ipAddress", ipAddress);
requestParams.setIpAddress(ipAddress);
putRequestParam("accountId", getParamValue("accountId"));
requestParams.setAccountId(getParamValue("accountId"));
putRequestParam("currentStatus", OrderDictConstants.OrderStatus.HAVE_ORDER);
requestParams.setCurrentStatus(OrderDictConstants.OrderStatus.HAVE_ORDER);
return super.onBeforeApiExecute();
}
@Override
public void handlerRequestBuilder(RequestMessage requestInfo, RequestBuilder requestBuilder, RequestParam requestParam) {
super.handlerRequestBuilder(requestInfo, requestBuilder, requestParam);
if (OrderRequestConfig.SAVE_ORDER_PROCESS_INFO.equals(requestInfo.getRequestCode())) {
requestParam.putRequestParam("ipAddress", getParamValue("ipAddress"));
requestParam.putRequestParam("orderTime", getParamValue("operateTime"));
requestParam.putRequestParam("orderStatus", getParamValue("currentStatus"));
requestParam.putRequestParam("orderId", getResultValue(OrderRequestConfig.SAVE_ORDER_INFO));
}
}
@Override
public boolean onAfterApiExecute(JSONObject resultSet) throws Exception {
// 依据付出办法获取订单信息
IPaymentFactory paymentExtend = ExtendFactory.getInstance().getPaymentExtend(getRequestParams().getPayWay());
if (paymentExtend != null) {
successResult(paymentExtend.placeOrder(getRequestParams()));
}
return super.onAfterApiExecute(resultSet);
}
}
至此,下单接口已完结,当用户付出成功后,会主动调起对应的付出回调接口。
因而,笔者欲界说一套根底付出回调告诉处理类,在详细付出回调接口,承继并完结即可。
付出回调接口目标类
完结根底回调完结类之前,笔者考虑顷刻,顿觉界说付出回调接口目标,用此作为详细回调接口的接口参数界说类。
此接口,现在界说两个需完结的函数,为“获取订单号”、“付出金额”用于回调接口时使用。
package com.threeox.biz.order.entity.inter;
import java.math.BigDecimal;
/**
* 付出告诉目标
*
* @author 赵屈犇
* @version 1.0
* @date 创立时刻: 2022/5/27 22:44
*/
public interface IPayNotifyInfo {
/**
* 获取订单号
*
* @return
*/
String getOrderNum();
/**
* 获取付出金额
*
* @return
*/
BigDecimal getPayMoney();
}
根底付出回调完结类
此类,先依据订单编号查询详细的订单信息。
当查询到详细订单信息时,调用子类完结的“是否付出成功”函数。
若,付出成功后,在此之下,校验付出金额是否共同。
若,付出金额共同时,更新订单信息,并存储订单进程记载。
在此之后,即是告诉详细事务完结类回调。
package com.threeox.biz.order.api.notify.base;
import com.alibaba.fastjson.JSONObject;
import com.threeox.biz.order.config.OrderDictConstants;
import com.threeox.biz.order.config.OrderRequestConfig;
import com.threeox.biz.order.entity.OrderInfo;
import com.threeox.biz.order.entity.inter.IPayNotifyInfo;
import com.threeox.biz.order.factory.inter.IOrderExtend;
import com.threeox.dblibrary.constants.GeneratedKeyInfo;
import com.threeox.drivenlibrary.engine.ExtendFactory;
import com.threeox.drivenlibrary.engine.config.DrivenEngineConfig;
import com.threeox.drivenlibrary.engine.constants.config.DrivenModelDBConstants;
import com.threeox.drivenlibrary.engine.entity.driven.config.OpenPlatformConfigMessage;
import com.threeox.drivenlibrary.engine.function.impl.AbstractApiExtend;
import com.threeox.drivenlibrary.engine.request.build.SqlBuilder;
import com.threeox.drivenlibrary.engine.request.execute.ExecuteRequestFactory;
import com.threeox.drivenlibrary.engine.request.inter.OnExecuteRequest;
import com.threeox.drivenlibrary.engine.util.RequestUtils;
import com.threeox.drivenlibrary.enums.dictionary.QueryType;
import com.threeox.utillibrary.date.TimeUtils;
/**
* 根底付出回调扩展类
*
* @author 赵屈犇
* @version 1.0
* @date 创立时刻: 2022/5/24 22:18
*/
public abstract class BasePayNotifyExtend<T extends IPayNotifyInfo> extends AbstractApiExtend<T> {
@Override
public boolean onBeforeApiExecute() throws Exception {
// 当前状况
String currentStatus = null;
IOrderExtend orderExtend = null;
ExecuteRequestFactory requestFactory = ExecuteRequestFactory.builder().setSqlExecutor(getSqlExecutor());
// 查询对应的订单信息
OrderInfo orderInfo = requestFactory.configCode(DrivenModelDBConstants.DRIVEN_MANAGE_MODEL_DB_CODE).requestCode(OrderRequestConfig.QUERY_ORDER_INFO)
.execute((OnExecuteRequest<SqlBuilder>) builder -> builder.and("order_num", QueryType.EQUAL, getRequestParams().getOrderNum()));
if (orderInfo != null) {
JSONObject updateData = new JSONObject();
OpenPlatformConfigMessage openPlatform = DrivenEngineConfig.getInstance().getOpenPlatform(orderInfo.getAppChannelCode());
if (openPlatform != null) {
boolean isPaySuccess = isPaySuccess(orderInfo, openPlatform);
if (isPaySuccess) {
// 校验付出金额是否共同
if (orderInfo.getPayMoney().compareTo(getRequestParams().getPayMoney()) == 0) {
currentStatus = OrderDictConstants.OrderStatus.PAYMENT_SUCCESS;
} else {
currentStatus = OrderDictConstants.OrderStatus.PAYMENT_AMOUNT_WRONG;
errorResult("付出金额不共同,请检查!");
}
} else {
currentStatus = OrderDictConstants.OrderStatus.PAYMENT_FAILED;
errorResult("验证失败,付出回调不成功!");
}
updateData.put("currentStatus", currentStatus);
updateData.put("operateTime", TimeUtils.getNowTimeDate());
updateData.put("ipAddress", RequestUtils.getIPAddress(servletRequest()));
// 更新订单信息
GeneratedKeyInfo keyInfo = requestFactory.requestCode(OrderRequestConfig.UPDATE_ORDER_INFO).requestParam(updateData).execute((OnExecuteRequest<SqlBuilder>) builder ->
builder.and("order_id", QueryType.EQUAL, orderInfo.getOrderId()));
if (keyInfo.toInteger() > 0) {
JSONObject processData = new JSONObject();
processData.put("processSnapshot", getParams().toJSONString());
processData.put("orderId", orderInfo.getOrderId());
processData.put("orderTime", updateData.get("operateTime"));
processData.put("orderStatus", updateData.get("currentStatus"));
processData.put("ipAddress", updateData.getString("ipAddress"));
// 保存订单进程
requestFactory.requestCode(OrderRequestConfig.SAVE_ORDER_PROCESS_INFO).requestParam(processData).execute();
}
} else {
errorResult("未找到装备的敞开信息!");
}
// 更新订单信息
orderExtend = ExtendFactory.getInstance().getOrderExtend(orderInfo.getBizType());
} else {
errorResult("未查询到对应的订单信息!");
}
if (orderExtend != null) {
orderExtend.handlePayNotify(getSqlExecutor(), orderInfo, getRequestParams(), currentStatus);
}
return super.onBeforeApiExecute();
}
/**
* 是否付出成功
*
* @param orderInfo
* @param openPlatform
* @return a
* @author 赵屈犇
* date 创立时刻: 2022/5/27 21:03
* @version 1.0
*/
protected abstract boolean isPaySuccess(OrderInfo orderInfo, OpenPlatformConfigMessage openPlatform) throws Exception;
}
至此,业已完结付出根底模块规划,下篇详细完结微信V2付出逻辑。