• 【业务功能篇104】 补充【业务功能篇99】微服务-springcloud-springboot-电商订单模块--整合支付


    在前面我们业务功能篇98-99中,我们介绍了电商项目中的订单模块服务,那么最后就是需要进行支付动作,那么我们这里就通过订阅第三方平台支付宝的支付调用接口功能,来进一步完成订单提交后的支付动作,支付宝的接口使用可以登录官网开发指南详情去了解

    SDK依赖引入

    在我们对应需要进行支付调用的订单服务中的pom文件加入依赖,其他服务不涉及的不需要加

    1. <dependency>
    2. <groupId>com.alipay.sdkgroupId>
    3. <artifactId>alipay-sdk-javaartifactId>
    4. <version>4.31.12.ALLversion>
    5. dependency>

    配置支付宝的配置文件类

    • 根据支付宝的接口使用方式,传递对应订单封装类对象,进行支付操作,并且还有同步回调地址,在支付完成之后自动跳转到我们指定页面
    •  回调地址:public static String return_url = "http://order.msb.com/orderPay/returnUrl"; 指定到该接口,该接口会进行支付完成后需要的操作,比如修改订单的状态为已完成,发货状态为待发货等等.. 然后return指定的html订单详情页面list.html
    1. /**
    2. * 支付宝的配置文件
    3. */
    4. //@ConfigurationProperties(prefix = "alipay")
    5. @Component
    6. @Data
    7. public class AlipayTemplate {
    8. // 商户appid 沙箱账号: tklalf8880@sandbox.com
    9. public static String APPID = "2021000121601310";
    10. // 私钥 pkcs8格式的
    11. public static String RSA_PRIVATE_KEY = "xx";
    12. // 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    13. public static String notify_url = "http://order.msb.com/payed/notify";
    14. // 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
    15. public static String return_url = "http://order.msb.com/orderPay/returnUrl";
    16. // 请求网关地址
    17. public static String URL = "https://openapi.alipaydev.com/gateway.do";
    18. // 编码
    19. public static String CHARSET = "UTF-8";
    20. // 返回格式
    21. public static String FORMAT = "json";
    22. // 支付宝公钥
    23. public static String ALIPAY_PUBLIC_KEY = "xx";
    24. // 日志记录目录
    25. public static String log_path = "/log";
    26. // RSA2
    27. public static String SIGNTYPE = "RSA2";
    28. public String pay(PayVo payVo){
    29. // SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需关注签名与验签
    30. //调用RSA签名方式
    31. AlipayClient client = new DefaultAlipayClient(URL,
    32. APPID,
    33. RSA_PRIVATE_KEY,
    34. FORMAT,
    35. CHARSET,
    36. ALIPAY_PUBLIC_KEY,
    37. SIGNTYPE);
    38. AlipayTradeWapPayRequest alipay_request=new AlipayTradeWapPayRequest();
    39. // 封装请求支付信息
    40. AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
    41. model.setOutTradeNo(payVo.getOut_trader_no());
    42. model.setSubject(payVo.getSubject());
    43. model.setTotalAmount(payVo.getTotal_amount());
    44. model.setBody(payVo.getBody());
    45. model.setTimeoutExpress("5000");
    46. model.setProductCode("11111");
    47. alipay_request.setBizModel(model);
    48. // 设置异步通知地址
    49. alipay_request.setNotifyUrl(notify_url);
    50. // 设置同步地址
    51. alipay_request.setReturnUrl(return_url);
    52. // form表单生产
    53. String form = "";
    54. try {
    55. // 调用SDK生成表单
    56. form = client.pageExecute(alipay_request).getBody();
    57. return form;
    58. } catch (AlipayApiException e) {
    59. // TODO Auto-generated catch block
    60. e.printStackTrace();
    61. }
    62. return null;
    63. }
    64. }

    支付接口 

    controller层  

    payOrder:在订单页面中,点击 支付宝发起支付请求的方法
    orderPay:支付完成之后,会同步回调到订单详情的方法,同时执行支付完成后需要的动作,比如修改订单状态为 关闭, 发货状态为待发货等等..
    1. @Controller
    2. public class OrderWebController {
    3. @Autowired
    4. private OrderService orderService;
    5. @Autowired
    6. AlipayTemplate alipayTemplate;
    7. /**
    8. * 获取订单相关信息
    9. * 然后跳转到支付页面 tklalf8880@sandbox.com
    10. * @param orderSn
    11. * @return
    12. */
    13. @GetMapping(value = "/payOrder",produces = "text/html")
    14. @ResponseBody
    15. public String payOrder(@RequestParam("orderSn") String orderSn){
    16. // 根据订单编号查询出相关的订单信息,封装到PayVO中
    17. PayVo payVo = orderService.getOrderPay(orderSn);
    18. String pay = alipayTemplate.pay(payVo);
    19. //System.out.println(pay);
    20. return pay;
    21. }
    22. @GetMapping("/orderPay/returnUrl")
    23. public String orderPay(@RequestParam(value = "orderSn",required = false) String orderSn,
    24. @RequestParam(value = "out_trade_no",required = false) String out_trade_no){
    25. // TODO 完成相关的支付操作
    26. System.out.println("orderSn = " + orderSn);
    27. if(StringUtils.isNotBlank(orderSn)){
    28. orderService.handleOrderComplete(orderSn);
    29. }else{
    30. //orderService.updateOrderStatus(out_trade_no,OrderConstant.OrderStateEnum.TO_SEND_GOODS.getCode());
    31. orderService.handleOrderComplete(out_trade_no);
    32. }
    33. return "list";
    34. }

    service层

    1. @Override
    2. //封装订单号对应的信息 返回给支付宝配置类的方法
    3. public PayVo getOrderPay(String orderSn) {
    4. // 根据订单号查询相关的订单信息
    5. OrderEntity orderEntity = this.getBaseMapper().getOrderByOrderSn(orderSn);
    6. // 通过订单信息封装 PayVO对象
    7. PayVo payVo = new PayVo();
    8. payVo.setOut_trader_no(orderSn);
    9. payVo.setTotal_amount(orderEntity.getTotalAmount().setScale(2, RoundingMode.UP).toString());
    10. // 订单名称和订单描述
    11. payVo.setSubject(orderEntity.getOrderSn());
    12. payVo.setBody(orderEntity.getOrderSn());
    13. return payVo;
    14. }
    15. @Override
    16. //支付完成之后,修改订单状态
    17. public void handleOrderComplete(String orderSn) {
    18. // 1.更新订单状态
    19. this.updateOrderStatus(orderSn,OrderConstant.OrderStateEnum.TO_SEND_GOODS.getCode());
    20. // TODO
    21. // 2.更新库存信息 库存数量递减
    22. // 3.购物车中的已经支付的商品移除
    23. // 4.更新会员积分 ....
    24. }

    前端核心请求跳转

     

    1. <form action="/orderPay/returnUrl" method="get">
    2. <input type="hidden" name="orderSn" th:value="${orderResponseVO.orderEntity.orderSn}">
    3. <li>
    4. <input type="submit" value="立即支付">
    5. li>
    6. form>
    7. <li>
    8. <img src="/static/order/pay/img\zhifubao.png" style="weight:auto;height:30px;" alt="">
    9. <a th:href="'/payOrder?orderSn='+${orderResponseVO.orderEntity.orderSn}">
    10. 支付宝
    11. a>
    12. li>

    支付宝支付完成之后的回调请求需要放过拦截器,否则会报错需要重新登录的,因为是不同的一个域名跳转,所以之前保存的用户登录session会话就不会带过来,所以需要放过这个请求接口

    new AntPathMatcher().match("/orderPay/**", requestURI)

    1. public class AuthInterceptor implements HandlerInterceptor {
    2. public static ThreadLocal threadLocal = new ThreadLocal();
    3. @Override
    4. public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    5. // 支付宝的回调我们放过
    6. String requestURI = request.getRequestURI();
    7. boolean match = new AntPathMatcher().match("/orderPay/**", requestURI);
    8. if(match){
    9. return true;
    10. }
    11. // 通过HttpSession获取当前登录的用户信息
    12. HttpSession session = request.getSession();
    13. Object attribute = session.getAttribute(AuthConstant.AUTH_SESSION_REDIS);
    14. if(attribute != null){
    15. MemberVO memberVO = (MemberVO) attribute;
    16. threadLocal.set(memberVO);
    17. return true;
    18. }
    19. // 如果 attribute == null 说明没有登录,那么我们就需要重定向到登录页面
    20. session.setAttribute(AuthConstant.AUTH_SESSION_MSG,"请先登录");
    21. response.sendRedirect("http://auth.msb.com/login.html");
    22. return false;
    23. }
    24. }

     

  • 相关阅读:
    RV1126编译ROS Kinetic环境
    Redis 读写分离和哨兵机制
    react类组件使用 【 实现数据+1 操作】
    经纬恒润汽车电子研发新成果亮相重庆智博会
    不直播不露脸也能做短视频变现,想挣点生活费试试这些玩法
    uniapp微信小程序局部刷新,无感刷新,修改哪条数据刷新哪条
    12_C++_链表_回调函数
    [NPUCTF2020]ezlogin xPATH注入
    星宿UI V2.1 开源wordpress资源下载小程序源码,流量主激励视频广告
    梳理 Pytorch 19个方面,70个核心操作全总结!
  • 原文地址:https://blog.csdn.net/studyday1/article/details/132812539