1、支付宝回调函数实现
我们在调试支付宝沙箱环境的时候,支护宝会有一个回调函数,也就是在支付成功之后,可以调用我们支付之后需要执行的相关方法,从而达到数据库的数据和我们的操作相统一。
首先我们先在本地将回调函数编写好~
在OrderController
类中新建我们的支付宝回调函数
*Controller
:
//支付宝回调函数
@RequestMapping("alipay_callback.do")
@ResponseBody
public Object alipayCallback(HttpServletRequest request) {
Map<String, String> params= Maps.newHashMap();
Map requestParams = request.getParameterMap();
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]+",";
}
params.put(name,valueStr);
}
logger.info("支付宝回调, sign:{},trade_status:{},参数:{}",params.get("sign"),params.get("trade_status"),params.toString());
//!!! 验证回调的正确性,是不是支付宝发了,而且还要避免重复通知
params.remove("sign_type");
try {
boolean alipayRSACheckedV2 = AlipaySignature.rsaCheckV2(params, Configs.getAlipayPublicKey(),"utf-8", Configs.getSignType());
if(!alipayRSACheckedV2){
return ServerResponse.createByErrorMessage("非法请求,验证不通过");
}
} catch (AlipayApiException e) {
logger.info("支付宝回调异常",e);
}
//TODO 验证各种数据
ServerResponse serverResponse = iOrderService.aliCallback(params);
if(serverResponse.isSuccess()){
return Const.AlipayCallback.RESPONSE_SUCCESS;
}
return Const.AlipayCallback.RESPONSE_FAILED;
}
*Service
:
//支付宝的回调通知接口
ServerResponse aliCallback(Map<String,String> params);
在Const
类中新增下面枚举函数:
public enum OrderStatusEnum{
CANCELED(0,"已取消"),
NO_PAY(10,"未支付"),
PAID(20,"已付款"),
SHIPPED(40,"已发货"),
ORDER_SUCCESS(50,"订单完成"),
OEDER_CLOSE(60,"订单关闭");
OrderStatusEnum(int code,String value){
this.code=code;
this.value=value;
}
public enum PayPlatformEnum{
ALIPAY(1,"支付宝");
PayPlatformEnum(int code,String value){
this.code=code;
this.value=value;
}
private String value;
private int code;
public String getValue() {
return value;
}
public int getCode() {
return code;
}
}
*ServiceImpl
:
//支付宝的回调通知接口
public ServerResponse aliCallback(Map<String,String> params){
// System.out.println("支付宝回调");
//订单号
Long orderNo = Long.parseLong(params.get("out_trade_no"));
//交易号
String tradeNo= params.get("trade_no");
//交易状态
String tradeStatus = params.get("trade_status");
// System.out.println("tradeStatus:"+tradeStatus);
Order order = orderMapper.selectByOrderNo(orderNo);
if(order == null){
// System.out.println("order == null");
return ServerResponse.createByErrorMessage("非该商场的订单,回调忽略");
}
if(order.getStatus() >= Const.OrderStatusEnum.PAID.getCode()){
// System.out.println("支付宝重复调用");
return ServerResponse.createBySuccess("支付宝重复调用");
}
String su="TRADE_SUCCESS";
if(su.equals(tradeStatus)){
// System.out.println("开始更新为支付完成状态");
order.setPaymentTime(DateTimeUtil.strToDate(params.get("gmt_payment")));
order.setStatus(Const.OrderStatusEnum.PAID.getCode());
orderMapper.updateByPrimaryKeySelective(order);
}
PayInfo payInfo =new PayInfo();
payInfo.setUserId(order.getUserId());
payInfo.setOrderNo(order.getOrderNo());
payInfo.setPayPlatform(Const.PayPlatformEnum.ALIPAY.getCode());
payInfo.setPlatformNumber(tradeNo);
payInfo.setPlatformStatus(tradeStatus);
payInfoMapper.insert(payInfo);
return ServerResponse.createBySuccess();
}
selectByOrderNo
这个方法需要我们自己编写:*Mapper
:
//根据订单号来查询订单是否存在
Order selectByOrderNo(Long orderNo);
*Mappler.xml
:
<select id="selectByOrderNo" resultMap="BaseResultMap" parameterType="long" >
select
<include refid="Base_Column_List"/>
from mmall_order
where order_no=#{orderNo}
</select>
2、查询用户订单状态接口
*Controller
:
//查询用户订单状态接口
@RequestMapping("query_order_pay_status.do")
@ResponseBody
public ServerResponse<Boolean> queryOrderPayStatus(HttpSession session,Long orderNo){
User user = (User) session.getAttribute(Const.CURRENT_USER);
if (user == null) {
return ServerResponse.createByErrorCodeMessage(ResponseCode.NEED_LOGIN.getCode(), ResponseCode.NEED_LOGIN.getDesc());
}
ServerResponse serverResponse = iOrderService.queryOrderPayStatus(user.getId(), orderNo);
if(serverResponse.isSuccess()){
return ServerResponse.createBySuccess(true);
}
return ServerResponse.createBySuccess(false);
}
*Service
:
//查询订单状态的接口实现
ServerResponse queryOrderPayStatus(Integer userId,Long orderNo);
*ServiceImpl
:
//查询订单状态的接口实现
public ServerResponse queryOrderPayStatus(Integer userId,Long orderNo){
Order order = orderMapper.selectByUserIdAndOrderNo(userId,orderNo);
if(order == null){
return ServerResponse.createByErrorMessage("用户没有该订单");
}
if(order.getStatus()>=Const.OrderStatusEnum.PAID.getCode()){
return ServerResponse.createBySuccess();
}
return ServerResponse.createByError();
}
selectByUserIdAndOrderNo
是重用上面的方法,所以不再贴出来~
3、接口测试
1、给沙箱环境配置我们的回调地址:
打开沙箱环境:https://openhome.alipay.com/platform/appDaily.htm
在图上所示配置我们的回调地址
由于我们是在本地开发,所以需要将本地IP映射到公网,
这个教程有讲怎么将本地IP映射到公网:https://blog.csdn.net/czjlghndcy/article/details/81130029
映射好公网IP之后,我们就将对应生成的共网IP以及定义的接口访问地址粘贴到沙箱环境中的回调地址中即可~
测试接口:
支付一个未支付的:
对生成的二维码进行支付
查询订单状态:
显示已支付,So,我们的回调接口以及订单状态查询接口测试成功啦