支付宝支付
第一步:alipay.properties
alipay_url=https://openapi.alipay.com/gateway.do #app的id app_id=2018020102122556 #私钥 app_private_key=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdQeknhM2rhiGAH6V0ljxn3rAWIdzduTEQuteTfwjnZtvMhQPuuN1b/88D5yMuaZhZNFeUdWb+SmtP9DAzAWWgnT13T0YhJcxP6txm7JBRrjadCRt+LOFxPiPQk5t9fH7yXjw9i4uMDsNJeTncrVZ/AZYrk0ESC9anJR8XeuBc3HE8T4fqlKKl35jlumIWrPbPNQhKGXaGcOnpiaXO9qYYUSP/tnrjNYXHOso0yBs4YTl+LLX2TJ12p3n/oX6HnL4zQgtN5k4QasHP7CIig1ngcVQGfWsMm4djI9KXNXvGLQPfMQEmyb71mM5OCdl1MtAc6OaIAymhSv2hOLNIuyodAgMBAAECggEAe05/P5mGm4QlKI2n8u8KlneqovASe1kG/BNFjkYB+VBR8OAr4TfbepPvAyRuFap+5xN/yMz14VcBJkRWtufVhEdHNxJV7w/wUIncIGhGEYYFFMVbZWhTrbQH6TiUp6TC9dCmc6vD1CKPRkFj+YGBXT0lPy3LzBa0TYNyCbszyhthrgkpuFYbB0R93IPvvBh5NJFXQytwNb2oVopC9AQWviqnZUZcT0eJ087dQ1WLPa6blBD8DP1PUq0Ldr6pgKfObFxIj8+87DlJznRfdEsbqZlS7jagdw5tLr71WJpctIGPqKpgvajfePP/lj3eY82BKQB+aTw0zmAiB05Yes4LgQKBgQDq3EiQR8J1MEN2rpiLt1WvDYYvKVUgOY7Od//fRPgaMBstbe4TzGBpR8E+z267bHAWLaWtHkfX6muFHn1x68ozEUWk/nZq0smWnuPdcy4E7Itbk36W2FF/rOZB7j5ddlC9byrxDSNgcf9/FA/CU+i5KVQpLYfsk2dvwomvu0aFVQKBgQCraXpxzMmsBx4127LsZDO5bxfxb6nqzyK4NPe0VaGiRg8oaCWczcLz1J5iRqC9QeEwsSt4XU1sYBMTcsFpA0apZpm3prH2HJRx/isNENesaHcihF0mMd0WxU3xyRvWSDeZV5A1Zy1ZEJ+p17DGwb2j+yo2uBrDNXBgBWEzXwiRqQKBgBdXFvsHtqKQzlOQHGbeLGy+KlSrheMy9Sc9s7cLkqB/oWPNZfifugEceW71jGqh5y29EZb3yGoDyPWsxwi4Rxr2H3a7Nyd8lT4bwkdyt+MTYvIR4WW6T7chhqyMsbP2GyYIUzsrdBWUnrCRXNOSJTGpksyY0sZHC+OGcMp/EQ4VAoGBAIISSVL/pm1+/UK7U1ukcced8JpKNLM0uVD1CJ50eHHOHgR4e0owrWYfioxisejLjBlJ6AWvL2g0w2T3qKKKVN2JOM4ulU5/w3l4+KwygqaWowizTogEQJPd5ta52ADTzjTzSD/t6nByd+YHAWLhc4lyt0bMj6pf68VBb8/upm75AoGAGAYz79IVHp9eppykufjNcWu6okkG8tZnzuyaWKW/CuKKBWMaTk0vcyQlfJfxIBccoQrBuYyXBdcpPuZ/ys2C25pNrkACuhIKNgnMc0floJoYEfJzetw/3cIimWu4NJzVQOaojaGA58oo2+fub43Xn25Jq4rvSVe3oLdb5xWkw5Q= #公钥 alipay_public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAhkZi6W0wn/prX+NIIF9ATb5Z8ReKK4hFYtBrweDfGHD1mNW7YIZY4G5hE7S2Sry8eFXlFgSlBWlJ4fVnDaK9MkVThpwE2H65ooVlK/wLuyPqovIVpMt/utva5Ayuzv7eQOWK45FdLDNDlK8QLoBko6SS+YbnWnf7a+mrf4NAS4UFClpfe8Byqe8XIraO2Cg4Ko5Y5schX39rOAH8GlLdgqQRYVQ2dCnkIQ+L+I4Cy9Mvw3rIkTwt3MBU+AqREXY4r5Bn6cmmX/9MAJbFqrofGiUAqG+qbjTcZAzgNPfuiD0zXgt/YYjMQMzck75BOmwnYOam2ajODUSQn8Xybsa7wQIDAQAB #回调地址 return_payment_url=http://localhost:8085/member/pay/alipay/callback/return #异步地址需要外网可以访问(暂时没有写) notify_payment_url=http://60.205.215.91/alipay/callback/notify
第二步:PayController
package com.macro.mall.portal.controller; import com.alibaba.fastjson.JSON; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayTradePagePayRequest; import com.macro.mall.common.api.CommonResult; import com.macro.mall.model.OmsOrderItem; import com.macro.mall.model.PaymentInfo; import com.macro.mall.portal.config.AlipayConfig; import com.macro.mall.portal.service.OmsPortalOrderService; import com.macro.mall.portal.service.PaymentService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import net.sf.json.JSONObject; 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.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.util.Date; import java.util.HashMap; import java.util.Iterator; import java.util.Map; /** * 支付管理 */ @Controller @Api(tags = "PayController", description = "支付管理") @RequestMapping("/member/pay") public class PayController { @Autowired private PaymentService paymentService; @Autowired private OmsPortalOrderService omsPortalOrderService; @Autowired AlipayClient alipayClient; @ApiOperation("去支付") @RequestMapping(value = "/alipay/submit", method = RequestMethod.GET) @ResponseBody public String goToPay( String orderSn, BigDecimal totalAmount) { //根据订单编号获取订单详情信息 OmsOrderItem omsOrderItem =omsPortalOrderService.getOrderByOrderSn(orderSn); //获取商品名称 String productName = omsOrderItem.getProductName(); //创建PC场景下单并支付请求对象 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();//创建API对应的request //设置同步返回地址,HTTP/HTTPS开头字符串 alipayRequest.setReturnUrl(AlipayConfig.return_payment_url); //支付宝服务器主动通知商户服务器里指定的页面http/https路径。 alipayRequest.setNotifyUrl(AlipayConfig.notify_payment_url);//在公共参数中设置回跳和通知地址 Map<String,String> requestMap = new HashMap<>(); requestMap.put("out_trade_no",orderSn);//订单编号 requestMap.put("product_code","FAST_INSTANT_TRADE_PAY");//产品交易码 requestMap.put("total_amount","0.01");//实际付款金额 requestMap.put("subject",productName);//商品名称 //填充业务参数 alipayRequest.setBizContent(JSON.toJSONString(requestMap)); String form=""; try { //调用SDK生成表单 form = alipayClient.pageExecute(alipayRequest).getBody(); } catch (AlipayApiException e) { e.printStackTrace(); } // 生成(保存)支付信息 PaymentInfo paymentInfo = new PaymentInfo(); paymentInfo.setOutTradeNo(orderSn); paymentInfo.setPaymentStatus("未支付"); paymentInfo.setOrderId(String.valueOf(omsOrderItem.getOrderId())); paymentInfo.setTotalAmount(totalAmount); paymentInfo.setSubject(productName); paymentInfo.setCreateTime(new Date()); paymentService.save(paymentInfo); // 发送检查支付结果的消息队列, paymentService.sendDelayPaymentCheck(orderSn,5); return form; } @ApiOperation("支付成功后同步回调转支付成功页面") @ResponseBody @RequestMapping(value = "/alipay/callback/return",method = RequestMethod.GET) public CommonResult callBackReturn(HttpServletRequest request){// 页面同步反转的回调 Map<String,String> paramsMap = new HashMap<String, String>(); Map parameterMap = request.getParameterMap(); for(Iterator<String> iter = parameterMap.keySet().iterator(); iter.hasNext();){ String name = iter.next(); String[] values = (String [])parameterMap.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1 ) ? valueStr + values [i] : valueStr + values[i] + ","; } paramsMap.put(name,valueStr); } String outTradeNo = request.getParameter("out_trade_no"); String tradeNo = request.getParameter("trade_no"); String sign = request.getParameter("sign"); try { boolean b = AlipaySignature.rsaCheckV1(paramsMap, AlipayConfig.alipay_public_key,AlipayConfig.charset,AlipayConfig.sign_type);// 对支付宝回调签名的校验 } catch (AlipayApiException e) { e.printStackTrace(); } //修改支付信息,幂等性检查 /* boolean b = paymentService.checkPaymentStatus(outTradeNo); if(!b){ PaymentInfo paymentInfo = paymentService.checkPaymentResult(outTradeNo); paymentService.updatePayment(request.getQueryString(),outTradeNo,tradeNo); //发送系统消息,出发并发商品支付业务消息队列 paymentService.sendPaymentSuccess(outTradeNo,paymentInfo.getPaymentStatus(),tradeNo); }*/ return CommonResult.success("支付成功"); } }
第三步:发送检查支付结果的消息队列
@Autowired private OmsOrderSettingMapper orderSettingMapper; @Autowired private AmqpTemplate amqpTemplate; /** * 发送检查支付结果的消息队列 * @param orderSn * @param count */ @Override public void sendDelayPaymentCheck(String orderSn, int count) { //获取订单超时时间 OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L); long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000; HashMap<Object, Object> hashMap = new HashMap<>(); hashMap.put("out_trade_no",orderSn); hashMap.put("count",count); //给延迟队列发送消息 amqpTemplate.convertAndSend(QueueEnum.QUEUE_PAY_CANCEL.getExchange(), QueueEnum.QUEUE_PAY_CANCEL.getRouteKey(), hashMap, new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { //给消息设置延迟毫秒值 message.getMessageProperties().setExpiration(String.valueOf(delayTimes)); return message; } }); }
第四步:处理发送检查支付结果的消息队列
package com.macro.mall.portal.component; import com.macro.mall.model.PaymentInfo; import com.macro.mall.portal.service.PaymentService; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; /** * 支付的处理者 */ @Component @RabbitListener(queues = "mall.pay.cancel") public class PayReceiver { @Autowired PaymentService paymentService; @RabbitHandler public void handle(HashMap mapMessage){ try { String outTradeNo = mapMessage.get("out_trade_no").toString(); int count = Integer.parseInt(mapMessage.get("count").toString()); // 如果没有支付成功,再次发送延迟检查队列 if (count > 0) { // 进行支付状态检查 System.out.println("正在进行第" + (6 - count) + "支付结果次检查"); //调用alipayClient接口,根据out_trade_no查询支付信息 PaymentInfo paymentInfo = paymentService.checkPaymentResult(outTradeNo); Thread thread = new Thread(); thread.start(); Thread.sleep(10000); //判断是否已经支付成功 if (paymentInfo.getPaymentStatus()!=null&&(paymentInfo.getPaymentStatus().equals("TRADE_SUCCESS") || paymentInfo.getPaymentStatus().equals("TRADE_FINISHED"))) { // 交易成功或者失败,记录交易状态 System.out.println("检查交易结果成功,记录交易状态。。。");// 修改支付的状态信息 // 修改支付信息 boolean b = paymentService.checkPaymentStatus(outTradeNo); if(!b){ //修改为已支付 paymentService.updatePayment(paymentInfo.getCallbackContent(),outTradeNo,paymentInfo.getAlipayTradeNo()); // 发送系统消息,出发并发商品支付业务消息队列 paymentService.sendPaymentSuccess(paymentInfo.getOutTradeNo(),paymentInfo.getPaymentStatus(),paymentInfo.getAlipayTradeNo()); } } else {//未支付 // 再次进行延迟检查 System.out.println("正在进行第" + (6 - count) + "支付结果次检查,检查用户尚未付款成功,继续巡检"); paymentService.sendDelayPaymentCheck(outTradeNo, count - 1); } } else { System.out.println("支付结果次检查次数耗尽,支付未果。。。"); } } catch (Exception e) { } } }
第五步:调用alipayClient接口,根据out_trade_no查询支付信息
@Autowired AlipayClient alipayClient; /** * 进行支付状态检查 * @param outTradeNo * @return */ @Override public PaymentInfo checkPaymentResult(String outTradeNo) { PaymentInfo paymentInfo = new PaymentInfo(); // 调用alipayClient接口,根据out_trade_no查询支付状态 AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); Map<String,Object> mapString = new HashMap<String,Object>(); mapString.put("out_trade_no",outTradeNo); String s = JSON.toJSONString(mapString); request.setBizContent(s); AlipayTradeQueryResponse response = null; try { response = alipayClient.execute(request); } catch (AlipayApiException e) { e.printStackTrace(); } // 等待付款、付款成功、付款失败、已经结束 paymentInfo.setCallbackTime(new Date()); paymentInfo.setOutTradeNo(outTradeNo); paymentInfo.setCallbackContent(response.getMsg()); if(response.isSuccess()){ System.out.println("交易已经创建"); paymentInfo.setPaymentStatus(response.getTradeStatus()); paymentInfo.setAlipayTradeNo(response.getTradeNo()); } else { System.out.println("交易未创建"); } return paymentInfo; }
第六步:发送系统消息,出发并发商品支付业务消息队列
@Autowired private OmsOrderSettingMapper orderSettingMapper; @Autowired private AmqpTemplate amqpTemplate; /** * 发送系统消息,出发并发商品支付业务消息队列 * @param outTradeNo * @param paymentStatus * @param tradeNo */ @Override public void sendPaymentSuccess(String outTradeNo, String paymentStatus, String tradeNo) { HashMap<String, String> hashMap = new HashMap<>(); hashMap.put("outTradeNo",outTradeNo); hashMap.put("paymentStatus",paymentStatus); hashMap.put("tradeNo",tradeNo); OmsOrderSetting orderSetting = orderSettingMapper.selectByPrimaryKey(1L); long delayTimes = orderSetting.getNormalOrderOvertime() * 60 * 1000; //给延迟队列发送消息 amqpTemplate.convertAndSend(QueueEnum.QUEUE_PAYMENT_SUCCESS_CANCEL.getExchange(), QueueEnum.QUEUE_PAYMENT_SUCCESS_CANCEL.getRouteKey(), hashMap, new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { //给消息设置延迟毫秒值 message.getMessageProperties().setExpiration(String.valueOf(delayTimes)); return message; } }); }
第七步:处理发送系统消息,出发并发商品支付业务消息队列
package com.macro.mall.portal.component; import com.macro.mall.portal.service.OmsOrderService; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; /** * 支付成功的处理者 */ @Component @RabbitListener(queues = "mall.paysuccess.cancel") public class PaySuccessReceiver { @Autowired private OmsOrderService orderService; @RabbitHandler public void handle(HashMap mapMessage){ String outTradeNo = mapMessage.get("outTradeNo").toString(); String trackingNo = mapMessage.get("tradeNo").toString(); String paymentStatus = mapMessage.get("paymentStatus").toString(); // 消费代码 orderService.updateOrder(outTradeNo,paymentStatus,trackingNo); // 发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口) orderService.sendOrderResult(outTradeNo); } }
第八步:发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口)
@Autowired private OmsOrderItemMapper omsOrderItemMapper; @Autowired private AmqpTemplate amqpTemplate; /** * 发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口) * @param outTradeNo */ @Override public void sendOrderResult(String outTradeNo) { OmsOrderItemExample omsOrderItemExample = new OmsOrderItemExample(); OmsOrderItemExample.Criteria criteria = omsOrderItemExample.createCriteria(); criteria.andOrderSnEqualTo(outTradeNo); List<OmsOrderItem> omsOrderItems = omsOrderItemMapper.selectByExample(omsOrderItemExample); OmsOrderItem omsOrder = omsOrderItems.get(0); Long productId = omsOrder.getProductId(); HashMap<String, Long> objectObjectHashMap = new HashMap<>(); objectObjectHashMap.put("productId",productId); //给延迟队列发送消息 amqpTemplate.convertAndSend(QueueEnum.QUEUE_STOCK_QUEUE.getExchange(), QueueEnum.QUEUE_STOCK_QUEUE.getRouteKey(),objectObjectHashMap, new MessagePostProcessor() { @Override public Message postProcessMessage(Message message) throws AmqpException { //给消息设置延迟毫秒值 message.getMessageProperties().setExpiration(String.valueOf(0)); return message; } }); }
第九步:处理发送一个订单成功的消息队列,由库存系统消费(或者调用库存接口)
package com.macro.mall.portal.component; import com.macro.mall.portal.service.PmsSkuStockService; import org.springframework.amqp.rabbit.annotation.RabbitHandler; import org.springframework.amqp.rabbit.annotation.RabbitListener; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import java.util.HashMap; @Component @RabbitListener(queues = "mall.stock.cancel") public class StockReserve { @Autowired private PmsSkuStockService pmsSkuStockService; @RabbitHandler public void handle(HashMap<String, Long> productId){ //根据订单编号查询该订单的商品数量 Integer productQuantity = pmsSkuStockService.getProductQuantity(productId); //根据商品id减卖家库存表的库存 pmsSkuStockService.updateOrderStock(productQuantity,productId.get("productId")); } }
如果对rabbitmq不熟悉的话可以查看https://blog.csdn.net/java_wxid/article/category/8663217