在本次项目当中,支付模块采用的是支付宝的扫码支付,初次设计了三个接口:支付接口pay.do、支付状态查询接口query_order_pay_status.do、支付宝回调接口alipay_callback.do。
其中支付回调接口的主要作用是:当用户付款成功之后,要求支付宝主动调用这个接口,进行订单的交易状态的修改,支付信息的保存等操作。
1.支付接口的设计
当用户提交订单之后,会向支付宝发送一个请求预下单,这个请求预下单包含很多的信息,包括订单号,是否有优惠的金额,验签,公钥等信息,传递给支付宝以后,支付宝会返回一个二维码信息,此二维码信息是一个http协议的信息,商城系统拿到二维码信息后,可以使用自己的工具包生成一个二维码,此二维码会持久化到图片服务器当中,然后将二维码地址以http的方式传递给前端,此时买家拿出支付宝扫码支付即可,当我们第一次扫码但是未支付的时候,会收到支付宝的第一次回调,这个回调当中有一些信息:订单号,金额,买家付款状态等,当我们输入密码以后,我们会收到第二次回调,如果输入密码时正确的,支付宝会给一个回调,包括付款的金额,还有对于支付宝订单最终的结果即tradeSuccess交易成功。
支付接口的业务流程:
1.支付接口传入的参数是orderNo,根据orderNo会获得Order,然后就是参数的校验
需要校验的参数有outTradeNo、totalAmount、undiscountableAmount、以及组装商品明细List<GoodsDetail>等等,具体可以从支付宝官方的demo当中查看。需要说明的是List<GoodsDetail>当中添加的商品是通过orderItem组的
List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
List<OrderItem> orderItemList=orderItemMapper.getOrderItemByOrderIdUserId(order.getOrderNo(),userId);
for(OrderItem orderItem:orderItemList){
GoodsDetail goods = GoodsDetail.newInstance(orderItem.getProductId().toString(), orderItem.getProductName(), BigDecimalUtil.mul(orderItem.getCurrentUnitPrice().doubleValue(),new Double(100).doubleValue()).longValue(), orderItem.getQuantity());
goodsDetailList.add(goods);
}
2.创建扫码支付请求builder,设置请求参数,在设置参数的时候需要设置回调函数
3.进行请求预下单,tradeService.tradePrecreate(builder);
4.根据请求预下单结果进行返回
2.请求预下单接口设计
当用户付款成功之后,要求支付宝主动调用这个接口,进行订单的交易状态的修改,支付信息的保存等操作。
1.查询订单是否存在
2.查询订单的支付状态
3.查看支付宝的tradeStatus(交易状态)是否是交易成功,成功则将订单的状态改为已付款
4.组装支付信息表
5.返回
3.查询订单的交易状态
这个很简单,根据userId和orderId查询即可
***************************controller**********************************
package com.mall.controller.portal;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.demo.trade.config.Configs;
import com.google.common.collect.Maps;
import com.mall.common.Const;
import com.mall.common.ResponseCode;
import com.mall.common.ServerResponse;
import com.mall.pojo.User;
import com.mall.service.IOrderService;
import com.sun.org.apache.xpath.internal.operations.Bool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Iterator;
import java.util.Map;
@Controller
@RequestMapping("/order/")
public class OrderController {
private static final Logger logger= LoggerFactory.getLogger(OrderController.class);
@Autowired
private IOrderService iOrderService;
//使用HttpServletRequest拿到servlet的上下文,然后upload文件夹,将后将二维码上传ftp,
@ResponseBody
@RequestMapping("pay.do")
public ServerResponse pay(HttpSession session, Long orderNo, HttpServletRequest request){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if(user==null){
return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(),ResponseCode.ILLEGAL_ARGUMENT.getMsg());
}
String path=request.getSession().getServletContext().getRealPath("upload");
return iOrderService.payOrder(path,user.getId(),orderNo);
}
@ResponseBody
@RequestMapping("alipay_callback.do")
public Object alipayCallback(HttpServletRequest request){
Map<String,String> params= Maps.newHashMap();
Map requestParams=request.getParameterMap();
//利用迭代器获取key
for(Iterator iter=requestParams.keySet().iterator();iter.hasNext();){
String name=(String)iter.next();
String [] values=(String [])requestParams.get(name);
String valueStr="";
for(int i=0;i<values.length;i++){
valueStr = (i==values.length-1)?valueStr+values[i] :valueStr+values[i]+",";
}
//将requestParams重置为params
params.put(name,valueStr);
}
logger.info("支付宝回调,sign:{},trade_status:{},参数:{}",params.get("sign"),params.get("trade_status"),params.toString());
//验证回调的正确性(是否是支付宝发的),还要避免重复通知,数据校验支付宝SDK已经做过了,此处可以直接调用,但是SDK没有除去sign_type,需要手动除去
/**
* 1.在通知返回参数列表中,除去sign、sign_type两个参数外,凡是通知返回回来的参数皆是待验签的参数。
*
*/
params.remove("sign_type");
try {
boolean alipayRSACheckedV2= AlipaySignature.rsaCheckV2(params, Configs.getAlipayPublicKey(),"utf-8",Configs.getSignType());
if(!alipayRSACheckedV2){
return ServerResponse.createByErrorMsg("非法请求,验证不通过");
}
} catch (AlipayApiException e) {
logger.error("支付宝参数验证异常",e);
}
//todo 验证各种数据
//业务逻辑
ServerResponse response=iOrderService.alipayCallback(params);
if(response.isSuccess()){
return Const.AlipayCallback.RESPONSE_SUCCESS;
}
return Const.AlipayCallback.RESPONSE_FAILED;
}
//前台轮训查询订单的支付状态,在用户进行扫码支付以后,前台会调用这个接口查看是否是付款成功,如果成功会返回订单成功界面
@ResponseBody
@RequestMapping("query_order_pay_status.do")
public ServerResponse<Boolean> query(HttpSession session, Long orderNo){
User user=(User) session.getAttribute(Const.CURRENT_USER);
if(user==null){
return ServerResponse.createByErrorCodeMsg(ResponseCode.ILLEGAL_ARGUMENT.getCode(),ResponseCode.ILLEGAL_ARGUMENT.getMsg());
}
ServerResponse response=iOrderService.queryOrderPayStatus(user.getId(),orderNo);
if(response.isSuccess()){
return ServerResponse.createBySuccess(true);
}
return ServerResponse.createBySuccess(false);
}
}
***************************service**********************************
package com.mall.service.impl;
import com.alipay.api.AlipayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.utils.ZxingUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mall.common.Const;
import com.mall.common.ServerResponse;
import com.mall.dao.OrderItemMapper;
import com.mall.dao.OrderMapper;
import com.mall.dao.PayInfoMapper;
import com.mall.pojo.Order;
import com.mall.pojo.OrderItem;
import com.mall.pojo.PayInfo;
import com.mall.service.IOrderService;
import com.mall.util.BigDecimalUtil;
import com.mall.util.DateTimeUtils;
import com.mall.util.FTPUtil;
import com.mall.util.PropertiesUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.ILoggerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Service("iOrderService")
public class OrderServiceImpl implements IOrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private PayInfoMapper payInfoMapper;
private static final Logger log= LoggerFactory.getLogger(OrderServiceImpl.class);
public ServerResponse payOrder(String path,Integer userId,long orderNo){
Map<String,String> map= Maps.newHashMap();
Order order=orderMapper.selectOrderByUserIdOrderNo(userId,orderNo);
if(order==null){
return ServerResponse.createByErrorMsg("该用户没有该订单");
}
map.put("orderNo",String.valueOf(order.getOrderNo()));
return test_trade_precreate(order,userId,path,map);
}
// 测试当面付2.0生成支付二维码
private ServerResponse test_trade_precreate(Order order,Integer userId,String path,Map map) {
// (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线,
// 需保证商户系统端不能重复,建议通过数据库sequence生成,
String outTradeNo = String.valueOf(order.getOrderNo());
// (必填) 订单标题,粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
String subject = new StringBuilder().append("happlymmall扫码支付,订单号:").append(outTradeNo).toString();
// (必填) 订单总金额,单位为元,不能超过1亿元
// 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
String totalAmount = String.valueOf(order.getPayment());
// (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段
// 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
String undiscountableAmount = "0";
// 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)
// 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID
String sellerId = "";
// 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"
String body = new StringBuilder().append("订单:").append(outTradeNo).append("购买商品共花费:").append(totalAmount).append("元").toString();
// 商户操作员编号,添加此参数可以为商户操作员做销售统计
String operatorId = "test_operator_id";
// (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
String storeId = "test_store_id";
// 业务扩展参数,目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法),详情请咨询支付宝技术支持
ExtendParams extendParams = new ExtendParams();
extendParams.setSysServiceProviderId("2088100200300400500");
// 支付超时,定义为120分钟
String timeoutExpress = "120m";
// 商品明细列表,需填写购买商品详细信息,
List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
List<OrderItem> orderItemList=orderItemMapper.getOrderItemByOrderIdUserId(order.getOrderNo(),userId);
for(OrderItem orderItem:orderItemList){
GoodsDetail goods = GoodsDetail.newInstance(orderItem.getProductId().toString(), orderItem.getProductName(), BigDecimalUtil.mul(orderItem.getCurrentUnitPrice().doubleValue(),new Double(100).doubleValue()).longValue(), orderItem.getQuantity());
goodsDetailList.add(goods);
}
/** 一定要在创建AlipayTradeService之前调用Configs.init()设置默认参数
* Configs会读取classpath下的zfbinfo.properties文件配置信息,如果找不到该文件则确认该文件是否在classpath目录
*/
Configs.init("zfbinfo.properties");
/** 使用Configs提供的默认参数
* AlipayTradeService可以使用单例或者为静态成员对象,不需要反复new
*/
AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
// 创建一个商品信息,参数含义分别为商品id(使用国标)、名称、单价(单位为分)、数量,如果需要添加商品类别,详见GoodsDetail
//GoodsDetail goods1 = GoodsDetail.newInstance("goods_id001", "xxx小面包", 1000, 1);
// 创建好一个商品后添加至商品明细列表
//goodsDetailList.add(goods1);
// 继续创建并添加第一条商品信息,用户购买的产品为“黑人牙刷”,单价为5.00元,购买了两件
//GoodsDetail goods2 = GoodsDetail.newInstance("goods_id002", "xxx牙刷", 500, 2);
//goodsDetailList.add(goods2);
// 创建扫码支付请求builder,设置请求参数
AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
.setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
.setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
.setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
.setTimeoutExpress(timeoutExpress)
.setNotifyUrl(PropertiesUtil.getProperty("alipay.callback.url"))//支付宝服务器主动通知商户服务器里指定的页面http路径,根据需要设置
.setGoodsDetailList(goodsDetailList);
AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
switch (result.getTradeStatus()) {
case SUCCESS:
log.info("支付宝预下单成功: )");
AlipayTradePrecreateResponse response = result.getResponse();
dumpResponse(response);
/**
* 下单成功,需要生成二维码,然后把二维码传到服务器上,最后组装url返回给前端
*/
File folder=new File(path);
String qrFileName=String.format("qr-%s.png",response.getOutTradeNo());//上传文件名
String qrPath = String.format(path+"/"+"qr-%s.png",response.getOutTradeNo());//获取上传文件的路径
//使用支付宝提供的工具生成二维码,根据路径生成二维码
ZxingUtils.getQRCodeImge(response.getQrCode(), 256, qrPath);
File targetFile=new File(path,qrFileName);
if(!targetFile.exists()){
targetFile.setWritable(true);//给予写权限,保证path下面的upload文件夹存在
targetFile.mkdirs();
}
FTPUtil.upload(Lists.newArrayList(targetFile));
log.info("qrPath:",qrPath);
String qrUrl=PropertiesUtil.getProperty("ftp.server.http.prefix")+"/"+targetFile.getName();
map.put("qrUrl",qrUrl);
return ServerResponse.createBySuccess(map);
case FAILED:
log.error("支付宝预下单失败!!!");
return ServerResponse.createByErrorMsg("支付宝预下单失败!!!");
case UNKNOWN:
log.error("系统异常,预下单状态未知!!!");
return ServerResponse.createByErrorMsg("系统异常,预下单状态未知!!!");
default:
log.error("不支持的交易状态,交易返回异常!!!");
return ServerResponse.createByErrorMsg("不支持的交易状态,交易返回异常!!!");
}
}
// 简单打印应答
private void dumpResponse(AlipayResponse response) {
if (response != null) {
log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
if (StringUtils.isNotEmpty(response.getSubCode())) {
log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
response.getSubMsg()));
}
log.info("body:" + response.getBody());
}
}
public ServerResponse alipayCallback(Map<String,String> params){
Long orderNo=Long.parseLong(params.get("out_trade_no"));//系统订单号
String tradeNo=params.get("trade_no");//支付宝订单号
String tradeStatus=params.get("trade_status");
//查询订单是否存在
Order order=orderMapper.selectOrderByOrderNo(orderNo);
if(order==null){
return ServerResponse.createByErrorMsg("非商城系统订单,回调忽略");
}
if(order.getStatus() >= Const.OrderStatusEnum.PAID.getCode()){
return ServerResponse.createBySuccessMsg("支付宝重复调用");//此时只要返回支付宝success即可
}
//查看支付宝的tradeStatus(交易状态)是否是交易成功,成功则将订单的状态改为已付款
if(Const.AlipayCallback.TRADE_STATUS_TRADE_SUCCESS.equals(tradeStatus)){
order.setUpdateTime(DateTimeUtils.strToDate(params.get("gmt_payment")));//更新订单的付款时间
order.setStatus(Const.OrderStatusEnum.PAID.getCode());
orderMapper.updateByPrimaryKey(order);
}
PayInfo payInfo=new PayInfo();
payInfo.setUserId(order.getUserId());
payInfo.setOrderNo(orderNo);
payInfo.setPayPlatform(Const.PayPlatEnum.ALIPAY.getCode());
payInfo.setPlatformNumber(tradeNo);
payInfo.setPlatformStatus(tradeStatus);
payInfoMapper.insert(payInfo);
return ServerResponse.createBySuccess();
}
public ServerResponse queryOrderPayStatus(Integer userId,Long orderNo){
Order order=orderMapper.selectOrderByUserIdOrderNo(userId, orderNo);
if(order==null){
return ServerResponse.createBySuccessMsg("用户没有该订单");
}
if(order.getStatus() >= Const.OrderStatusEnum.PAID.getCode()){
return ServerResponse.createBySuccess();
}
return ServerResponse.createByError();
}
}
*********************************xml**************************
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.mall.dao.OrderMapper" >
<resultMap id="BaseResultMap" type="com.mall.pojo.Order" >
<constructor >
<idArg column="id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="order_no" jdbcType="BIGINT" javaType="java.lang.Long" />
<arg column="user_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="shipping_id" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="payment" jdbcType="DECIMAL" javaType="java.math.BigDecimal" />
<arg column="payment_type" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="postage" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="status" jdbcType="INTEGER" javaType="java.lang.Integer" />
<arg column="payment_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="send_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="end_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="close_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="create_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
<arg column="update_time" jdbcType="TIMESTAMP" javaType="java.util.Date" />
</constructor>
</resultMap>
<sql id="Base_Column_List" >
id, order_no, user_id, shipping_id, payment, payment_type, postage, status, payment_time,
send_time, end_time, close_time, create_time, update_time
</sql>
<select id="selectByPrimaryKey" resultMap="BaseResultMap" parameterType="java.lang.Integer" >
select
<include refid="Base_Column_List" />
from mmall_order
where id = #{id,jdbcType=INTEGER}
</select>
<delete id="deleteByPrimaryKey" parameterType="java.lang.Integer" >
delete from mmall_order
where id = #{id,jdbcType=INTEGER}
</delete>
<insert id="insert" parameterType="com.mall.pojo.Order" >
insert into mmall_order (id, order_no, user_id,
shipping_id, payment, payment_type,
postage, status, payment_time,
send_time, end_time, close_time,
create_time, update_time)
values (#{id,jdbcType=INTEGER}, #{orderNo,jdbcType=BIGINT}, #{userId,jdbcType=INTEGER},
#{shippingId,jdbcType=INTEGER}, #{payment,jdbcType=DECIMAL}, #{paymentType,jdbcType=INTEGER},
#{postage,jdbcType=INTEGER}, #{status,jdbcType=INTEGER}, #{paymentTime,jdbcType=TIMESTAMP},
#{sendTime,jdbcType=TIMESTAMP}, #{endTime,jdbcType=TIMESTAMP}, #{closeTime,jdbcType=TIMESTAMP},
now(), now())
</insert>
<insert id="insertSelective" parameterType="com.mall.pojo.Order" >
insert into mmall_order
<trim prefix="(" suffix=")" suffixOverrides="," >
<if test="id != null" >
id,
</if>
<if test="orderNo != null" >
order_no,
</if>
<if test="userId != null" >
user_id,
</if>
<if test="shippingId != null" >
shipping_id,
</if>
<if test="payment != null" >
payment,
</if>
<if test="paymentType != null" >
payment_type,
</if>
<if test="postage != null" >
postage,
</if>
<if test="status != null" >
status,
</if>
<if test="paymentTime != null" >
payment_time,
</if>
<if test="sendTime != null" >
send_time,
</if>
<if test="endTime != null" >
end_time,
</if>
<if test="closeTime != null" >
close_time,
</if>
<if test="createTime != null" >
create_time,
</if>
<if test="updateTime != null" >
update_time,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides="," >
<if test="id != null" >
#{id,jdbcType=INTEGER},
</if>
<if test="orderNo != null" >
#{orderNo,jdbcType=BIGINT},
</if>
<if test="userId != null" >
#{userId,jdbcType=INTEGER},
</if>
<if test="shippingId != null" >
#{shippingId,jdbcType=INTEGER},
</if>
<if test="payment != null" >
#{payment,jdbcType=DECIMAL},
</if>
<if test="paymentType != null" >
#{paymentType,jdbcType=INTEGER},
</if>
<if test="postage != null" >
#{postage,jdbcType=INTEGER},
</if>
<if test="status != null" >
#{status,jdbcType=INTEGER},
</if>
<if test="paymentTime != null" >
#{paymentTime,jdbcType=TIMESTAMP},
</if>
<if test="sendTime != null" >
#{sendTime,jdbcType=TIMESTAMP},
</if>
<if test="endTime != null" >
#{endTime,jdbcType=TIMESTAMP},
</if>
<if test="closeTime != null" >
#{closeTime,jdbcType=TIMESTAMP},
</if>
<if test="createTime != null" >
now(),
</if>
<if test="updateTime != null" >
now(),
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="com.mall.pojo.Order" >
update mmall_order
<set >
<if test="orderNo != null" >
order_no = #{orderNo,jdbcType=BIGINT},
</if>
<if test="userId != null" >
user_id = #{userId,jdbcType=INTEGER},
</if>
<if test="shippingId != null" >
shipping_id = #{shippingId,jdbcType=INTEGER},
</if>
<if test="payment != null" >
payment = #{payment,jdbcType=DECIMAL},
</if>
<if test="paymentType != null" >
payment_type = #{paymentType,jdbcType=INTEGER},
</if>
<if test="postage != null" >
postage = #{postage,jdbcType=INTEGER},
</if>
<if test="status != null" >
status = #{status,jdbcType=INTEGER},
</if>
<if test="paymentTime != null" >
payment_time = #{paymentTime,jdbcType=TIMESTAMP},
</if>
<if test="sendTime != null" >
send_time = #{sendTime,jdbcType=TIMESTAMP},
</if>
<if test="endTime != null" >
end_time = #{endTime,jdbcType=TIMESTAMP},
</if>
<if test="closeTime != null" >
close_time = #{closeTime,jdbcType=TIMESTAMP},
</if>
<if test="createTime != null" >
create_time = #{createTime,jdbcType=TIMESTAMP},
</if>
<if test="updateTime != null" >
update_time = now(),
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
<update id="updateByPrimaryKey" parameterType="com.mall.pojo.Order" >
update mmall_order
set order_no = #{orderNo,jdbcType=BIGINT},
user_id = #{userId,jdbcType=INTEGER},
shipping_id = #{shippingId,jdbcType=INTEGER},
payment = #{payment,jdbcType=DECIMAL},
payment_type = #{paymentType,jdbcType=INTEGER},
postage = #{postage,jdbcType=INTEGER},
status = #{status,jdbcType=INTEGER},
payment_time = #{paymentTime,jdbcType=TIMESTAMP},
send_time = #{sendTime,jdbcType=TIMESTAMP},
end_time = #{endTime,jdbcType=TIMESTAMP},
close_time = #{closeTime,jdbcType=TIMESTAMP},
create_time = #{createTime,jdbcType=TIMESTAMP},
update_time = now()
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectOrderByUserIdOrderNo" parameterType="map" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from mmall_order
where order_no = #{orderNo} and user_id = #{userId}
</select>
<select id="selectOrderByOrderNo" parameterType="long" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from mmall_order
where order_no=#{orderNo}
</select>
</mapper>
网友评论