支付服务-----功能实现逻辑

简介: 支付服务-----功能实现逻辑

支付服务实现逻辑

简单概况一下支付服务的实现逻辑

通过支付宝的沙箱环境来模拟支付功能,用户点击支付宝的链接后给后端发/aliPayOrder请求,封装支付宝需要payVo对象,并且调用 String pay = alipayTemplate.pay(payVo)和 return pay;来调用支付宝沙箱环境提供的支付页面(这里返回的pay是一个html页面,直接给浏览器渲染后就是支付宝提供的支付页面),这是支付宝官方写好了的,模拟支付宝支付的过程,专门用来给开发人员测试用的,用户输入自己的支付宝账号密码成功支付后就会发请求memberOrder.html,这其实就是支付成功后跳转到用户的订单页面,这个页面会呈现用户的所有订单记录,所以这个请求会把用户的订单数据都封装好,并且把这些数据渲染到订单页面,但是刚支付成功的订单的状态还是待支付,这就有问题了,最后通过支付宝支付成功后的异步回调来修改刚支付成功的订单状态为已支付(异步回调其实就是支付成功后支付宝会给一个地址发送一个请求来告诉你支付成功了)


1、支付使用的是支付宝的沙箱环境来模拟测试的

官网:登录 - 支付宝

2、在订单服务的config文件里配置下面的支付宝支付沙箱环境(常量)

package com.saodai.saodaimall.order.config;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.saodai.saodaimall.order.vo.PayVo;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
 * 支付宝支付沙箱环境配置
 */
@ConfigurationProperties(prefix = "alipay")
@Component
@Data
public class AlipayTemplate {
    // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
    public String app_id;
    // 商户私钥,您的PKCS8格式RSA2私钥
    public String merchant_private_key;
    // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
    public String alipay_public_key;
    // 服务器[异步通知]页面路径  需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    // 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
    public String notify_url;
    // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    //同步通知,支付成功,一般跳转到成功页
    public String return_url;
    // 签名方式
    private  String sign_type;
    // 字符编码格式
    private  String charset;
    //订单超时时间(用于收单,防止用户支付很慢,导致订单过期自动关了后再支付订单的情况)
    private String timeout = "1m";
    // 支付宝网关; https://openapi.alipaydev.com/gateway.do
    public String gatewayUrl;
    public  String pay(PayVo vo) throws AlipayApiException {
        //AlipayClient alipayClient = new DefaultAlipayClient(AlipayTemplate.gatewayUrl, AlipayTemplate.app_id, AlipayTemplate.merchant_private_key, "json", AlipayTemplate.charset, AlipayTemplate.alipay_public_key, AlipayTemplate.sign_type);
        //1、根据支付宝的配置生成一个支付客户端
        AlipayClient alipayClient = new DefaultAlipayClient(gatewayUrl,
                app_id, merchant_private_key, "json",
                charset, alipay_public_key, sign_type);
        //2、创建一个支付请求 //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(return_url);
        alipayRequest.setNotifyUrl(notify_url);
        //商户订单号,商户网站订单系统中唯一订单号,必填
        String out_trade_no = vo.getOut_trade_no();
        //付款金额,必填
        String total_amount = vo.getTotal_amount();
        //订单名称,必填
        String subject = vo.getSubject();
        //商品描述,可空
        String body = vo.getBody();
        alipayRequest.setBizContent("{\"out_trade_no\":\""+ out_trade_no +"\","
                + "\"total_amount\":\""+ total_amount +"\","
                + "\"subject\":\""+ subject +"\","
                + "\"body\":\""+ body +"\","
                + "\"timeout_express\":\""+timeout+"\","
                + "\"product_code\":\"FAST_INSTANT_TRADE_PAY\"}");
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        //会收到支付宝的响应,响应的是一个页面,只要浏览器显示这个页面,就会自动来到支付宝的收银台页面
        System.out.println("支付宝的响应:"+result);
        return result;
    }
}


3、在application.properties配置真正自己的沙箱环境配置

#支付宝相关的配置
#应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
alipay.app_id=2021000119644301
#商户私钥,用的是RSA2私钥
alipay.merchant_private_key=MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCNO1TNy1L65dxxrcmYwo452ClW8rpJsshk9fiToCDSC3Fz0SZQlGYwqGxXr0NzzLvf0sHmIK49CXwXfPgYZPSxaCQSJVm7r87sAEoDi75w0gH0dt+m4viN0GzSGYXVdAfO2J/1BqJoNlpVah3vb3UwLIYpVmNRY6TNdDxnZbpB2Hcosjo8PXvEwqU5MS1W16VkRSkEwPUw/gkKLFUrDqbes5JgJeneAkCPuGa18rNMHxugibVKutfj7MFdomLaNMB2hNOapH3matKJ6JZi/uSqBNLWxfr8kUCw4t8tjJjNaisSfqYwjM9EeWTkkbcba02VUvziB6DqFCue9nV0MVkDAgMBAAECggEAYbHHCcw6DGBwyxoiN89tPsouXnztLAnF4UDcwJGl4mYUBr+It3jP75yxxT3xdOsMktlhU2UL4iDre/vwSj+bnBSjzwGTPudwRYQ1rpo+FCDRRV/tea3LrZ2diQAquerXc9gZXg9GzLu8ZRVQu83nzHkgHPwrG6PH3m8nUYbm/qBM2Fq6nH6AyybXdUk8iwNpLvy/wQkfxPIfZglQqHlEW9x96hs+n/GUx/S4mKFxT6L8MNd7K/rez/xPSGzjPcG1+UkI8VeWQLSnBmfFrCVFrl87rXk6x/6gnY5nogFmKafAvip6hR0/+50vGtWqU/HgeyDc9q/xyLwYy4pulgeRkQKBgQDJqiJjx9WRlC5tfUuwGf2puuwCgu+vqofbE0RuSZtBvb92M65yR+ZtuFkZADOu/ldf5+dITtc1+QpUXCxCvyO+l+w2f0S9oHkfhTmIx6A+jH0spvXfVuZOe97kh2YF3wkAJMd2XBUOEN2xLSeqf62aQxAtfB0zGGZ5iCnoWGbPRwKBgQCzSNPg2XsBb0YVLHtfSOQfuIn7NRHyjznya/9d5cP2HTXgQYMVoJDTKP8ZOwmDFWkRf/DRJEmUGaV5+nJpXa8fyBTkHCCzAEzu8CK2zVQuLPPG9TQXh3t8STEruAu3Sq99LtF8kDhA/8MrmgXmMyhqJGN+jBhwGLq7RekUOg7eZQKBgHLUGpLgZd5oFuunTaKvmf28fsiLT/mhy4vV88Asz2fmqI+gq/NMt4vATZNrxwIctxnYDZzhr69+5//TICy9c5gCH7GEVFr5dh6ZmIIm0TrsehYj15rde3QzGl7cLh6nuhNH3f+qPR7uQZ2yTYTLAMn2585Ofr3qZedLvjkbpSbfAoGBAJZOWFQKALYTNA5MXKJl2ds+O2//7iwNJ+e140I1fzS3CJQaWGupUcG2fSgJ9s+PA6dIO/0bDxS666B397Oed1ONyvXzHvbzKYyohnH7crfDuBz1NdcEHuLz+eVNR4VDeBzbQ4XK416bDmVfm9KC0T8rgr51dYeFNAgNdHsgsZaBAoGAF4sYuVYF2iv9ZTmYMbf9DNv5Px25v2j2RD0pyW+haR2Jq6NqLlGwV/wnFDNAR1BTnFh3vNM1loaw897qORW8bNnAhDGH91jz+pSiCfV4mu9CXDoIw/ZxBfgdxGX7FI7EWPtSG3qb029Vtezks0OW9VROC3I0qePqVeLF8rV6tuE=
#支付宝公钥
alipay.alipay_public_key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAh3IVA56nyTr1Gt33gC5RAbtIVh+pMg1z9ad3VC5h0QPyU0dHYS+j4PbDjeR7kA/Gz3Q7gcp1vo+H4NTBeaQ3m0vG/+UW2wuT6GNeNT8g59gDElE9LtSpqZzsHZMFHKzsvY5n/2v8ADrF16t/TfNnsKvkSCO7Rtcc2mJZtBvZF/APXLn4mbdSs8v5f4o4/RU/iKyKjIUiWfl58JCLD0JYVMxGUcv1Sh9q+1irv4KrP+J/L77eaJ6FiXHX7aXxhsPZQnHy+4KUsjgst1vuYlhpTX9h9GSKiBlFvjTamQhrPtfPfkqa0bsHHmOjToE6gatwDFER0f0kH5gxgo1x1HK0+QIDAQAB
#异步回调地址(支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息)
alipay.notify_url=http://vtyk0jgqvh.51xd.pub/payed/notify
#同步通知地址(支付成功后跳转到指定的地址,这里是跳到最终的订单页面)
alipay.return_url=http://member.saodaimall.com/memberOrder.html
#签名方式
alipay.sign_type=RSA2
alipay.charset=utf-8
#支付宝网关
alipay.gatewayUrl=https://openapi.alipaydev.com/gateway.do
spring.mvc.date-format=yyyy-MM-dd HH:mm:ss


上面要配置的内容有应用ID、商户私钥、支付宝公钥、异步回调地址、同步通知地址即可,然后再沙箱中配置好商户的公钥即可

(1)在上面的官网查看APPID

(2)选择支付加密方式为RSA2(非对称加密方式)

RSA2(非对称加密方式)图解

在这里也就是商户和支付宝两者之间有两对密钥,每一对都是一把公钥一把私钥,其中支付宝的私钥是只有支付宝官方核心人员才知道的

点击上图的查看就可以更换密钥


下载支付宝密钥生成器生成密钥

生成的应用私钥是要配置到支付宝的组件配置中去的,应用公钥给支付宝的沙箱后支付宝也会告诉你一个支付宝的公钥,这个要配置到支付宝的组件配置中。


图解:上面的配置商户私钥(自己的私钥)alipay.merchant_private_key的值就是上面生成密钥的应用私钥,把上面应用公钥(商户公钥)复制到下面公钥字符的区域(其实就是把你自己的公钥(商户公钥)告诉支付宝),点击保存设置后支付宝就知道了你的公钥,然后它会告诉你它的公钥是什么,直接复制并配置到application.properties配置文件里的支付宝公钥alipay.alipay_public_key的值(只需要在配置文件中配置两把钥匙,还有一把是商户公钥,这把不需要配置,因为点击保持后支付宝已经知道了你的公钥)


4、前台设置点击支付宝支付跳转的链接(发请求/aliPayOrder给后端)

<li>
  <img src="/static/order/pay/img/zhifubao.png" style="weight:auto;height:30px;" alt="">
  <a th:href="'http://order.saodaimall.com/aliPayOrder?orderSn='+${submitOrderResp.order.orderSn}">支付宝</a>
</li>

5、在订单服务的web文件的PayWebController控制器处理前面的发的请求/aliPayOrder

package com.saodai.saodaimall.order.web;
import com.alipay.api.AlipayApiException;
import com.saodai.saodaimall.order.config.AlipayTemplate;
import com.saodai.saodaimall.order.service.OrderService;
import com.saodai.saodaimall.order.vo.PayVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
/**
* 支付宝控制器
**/
@Slf4j
@Controller
public class PayWebController {
    @Autowired
    private AlipayTemplate alipayTemplate;
    @Autowired
    private OrderService orderService;
    /**
    * 用户下单:支付宝支付
    * 1、让支付页让浏览器展示
    * 2、支付成功以后,跳转到用户的订单列表页
    * @param orderSn
    * @return
    * @throws AlipayApiException
    */
    @ResponseBody
    @GetMapping(value = "/aliPayOrder",produces = "text/html")//produces = "text/html"表示返回的类型是html
    public String aliPayOrder(@RequestParam("orderSn") String orderSn) throws AlipayApiException {
         //getOrderPay方法是为了封装PayVo对象
        PayVo payVo = orderService.getOrderPay(orderSn);
        //这里返回的pay是一个html页面,直接给浏览器渲染就行了
        String pay = alipayTemplate.pay(payVo);
        //        System.out.println(pay);
        return pay;
    }
}

getOrderPay方法是为了封装PayVo对象,分流程:

1、根据订单号查询到订单

2、格式化付款金额并封装到PayVo

3、获取订单的第一个订单项,把商品销售属性组合(JSON)作为商品描述

  /**
     * 获取当前订单的支付信息(支付宝支付)
     * @param orderSn
     * @return
     */
    @Override
    public PayVo getOrderPay(String orderSn) {
        PayVo payVo = new PayVo();
        //根据订单号查询到订单
        OrderEntity orderInfo = this.getOrderByOrderSn(orderSn);
        //因为数据库保存的是小数点后四位,这里要转为2位(setScale(2, BigDecimal.ROUND_UP)表示保留两位小数点,向上取值)
        BigDecimal payAmount = orderInfo.getPayAmount().setScale(2, BigDecimal.ROUND_UP);
        //设置付款金额
        payVo.setTotal_amount(payAmount.toString());
        //商户订单号
        payVo.setOut_trade_no(orderInfo.getOrderSn());
        //查询订单项的数据
        List<OrderItemEntity> orderItemInfo = orderItemService.list(
                new QueryWrapper<OrderItemEntity>().eq("order_sn", orderSn));
         //获取订单的第一个订单项
        OrderItemEntity orderItemEntity = orderItemInfo.get(0);
        //把商品销售属性组合(JSON)作为商品描述
        payVo.setBody(orderItemEntity.getSkuAttrsVals());
         //把商品sku名字作为设置订单名称
        payVo.setSubject(orderItemEntity.getSkuName());
        return payVo;
    }
package com.saodai.saodaimall.order.vo;
import lombok.Data;
/**
 * 支付宝支付需要用到的数据封装类
 */
@Data
public class PayVo {
    private String out_trade_no; // 商户订单号 必填
    private String subject; // 订单名称 必填
    private String total_amount;  // 付款金额 必填
    private String body; // 商品描述 可空
}

6、第五步处理成功后会执行下面链接的跳转

这个memberOrder.html其实就是订单服务的所有订单界面(用户的所有订单)

#同步通知,支付成功,一般跳转到成功页

alipay.return_url=http://member.saodaimall.com/memberOrder.html

7、在会员服务的web包的MemberWebController控制器来处理请求/memberOrder.html(这里进行了分页处理)

package com.saodai.saodaimall.member.web;
import com.alibaba.fastjson.JSON;
import com.saodai.common.utils.R;
import com.saodai.saodaimall.member.feign.OrderFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;
/**
 *支付宝支付成功后回调页面处理器
 **/
@Controller
public class MemberWebController {
    @Autowired
    private OrderFeignService orderFeignService;
    @GetMapping(value = "/memberOrder.html")
    public String memberOrderPage(@RequestParam(value = "pageNum",required = false,defaultValue = "0") Integer pageNum,
                                  Model model, HttpServletRequest request) {
        //获取到支付宝给我们转来的所有请求数据
        //request,验证签名
        //查出当前登录用户的所有订单列表数据
        Map<String,Object> page = new HashMap<>();
        page.put("page",pageNum.toString());
        //远程查询订单服务订单数据
        R orderInfo = orderFeignService.listWithItem(page);
        System.out.println(JSON.toJSONString(orderInfo));
        model.addAttribute("orders",orderInfo);
        return "orderList";
    }
}


1)远程调用订单服务来查询所有订单信息

 /**
     * 分页查询当前登录用户的所有订单信息(用于前台我的订单里的数据回显)
     * @param params
     * @return
     */
    @PostMapping("/listWithItem")
    //@RequiresPermissions("order:order:list")
    public R listWithItem(@RequestBody Map<String, Object> params){
        PageUtils page = orderService.queryPageWithItem(params);
        return R.ok().put("page", page);
    }

(2)OrderServiceImpl的queryPageWithItem方法具体实现

分流程:

1、按会员id去查询所有订单,然后按创建时间做降序排列(也就是最新的订单会在第一个显示)

2、遍历所有订单集合(封装List<OrderEntity>中的订单项的数据)

 /**
     * 分页查询当前登录用户的所有订单信息(用于前台我的订单里的数据回显)
     */
    @Override
    public PageUtils queryPageWithItem(Map<String, Object> params) {
        MemberResponseVo memberResponseVo = LoginUserInterceptor.loginUser.get();
        //按会员id去查询所有订单,然后按创建时间做降序排列(也就是最新的订单会在第一个显示)
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
                        .eq("member_id",memberResponseVo.getId()).orderByDesc("create_time")
        );
        //遍历所有订单集合(封装订单项)
        List<OrderEntity> orderEntityList = page.getRecords().stream().map(order -> {
            //根据订单号查询订单项里的数据
            List<OrderItemEntity> orderItemEntities = orderItemService.list(new QueryWrapper<OrderItemEntity>()
                    .eq("order_sn", order.getOrderSn()));
            order.setOrderItemEntityList(orderItemEntities);
            return order;
        }).collect(Collectors.toList());
        page.setRecords(orderEntityList);
        return new PageUtils(page);
    }

8、通过支付宝支付成功后的异步回调来修改支付成功后订单页面的订单项的状态

(1)在支付宝沙箱环境配置中有以下配置


这个配置就是表示支付宝支付成功后会有一个支付成功的异步消息发送到这个url地址(特别注意的是这个地址必须是外网能够访问的到得道地址,vtyk0jgqvh.51xd.pub是买了内网穿透后给的地址,外网可以访问到的地址,它和本机的order.saodaimall.com地址是对应的),告诉我们支付成功了,这里就可以通过这个地址来修改订单的状态(也就是把支付宝支付成功后的订单状态由待付款自动修改成已支付状态),这个请求会按固定的时间间隔来发送请求,直到返回“success”才会停止发送请求(发完固定次数也会停止)


#支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息

alipay.notify_url=http://vtyk0jgqvh.51xd.pub/payed/notify

(2)上面的/payed/notify请求由订单服务的listener包的OrderPayedListener控制器来处理


package com.saodai.saodaimall.order.listener;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.saodai.saodaimall.order.config.AlipayTemplate;
import com.saodai.saodaimall.order.service.OrderService;
import com.saodai.saodaimall.order.vo.PayAsyncVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
/**
* 订单支付成功控制器(支付宝支付成功后的异步通知)
* 支付宝会悄悄的给我们发送一个请求,告诉我们支付成功的信息
* 只要收到支付宝的异步通知,返回 success 支付宝便不再通知(在通知之前需要验签)
*/
@RestController
public class OrderPayedListener {
    @Autowired
    private OrderService orderService;
    @Autowired
    private AlipayTemplate alipayTemplate;
    @PostMapping(value = "/payed/notify")
    public String handleAlipayed(PayAsyncVo asyncVo, HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
        // 获取支付宝POST过来反馈信息
        //TODO 需要验签
        Map<String, String> params = new HashMap<>();
        Map<String, String[]> requestParams = request.getParameterMap();
        for (String name : requestParams.keySet()) {
            String[] values = requestParams.get(name);
            String valueStr = "";
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i]
                    : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用
            // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
            params.put(name, valueStr);
        }
        //alipayTemplate.getAlipay_public_key()是支付宝公钥 alipayTemplate.getCharset()字符编码格式 alipayTemplate.getSign_type()签名方式
        boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayTemplate.getAlipay_public_key(),
                                                          alipayTemplate.getCharset(), alipayTemplate.getSign_type()); //调用SDK验证签名
        if (signVerified) {
            System.out.println("签名验证成功...");
            //去修改订单状态
            String result = orderService.handlePayResult(asyncVo);
            return result;
        } else {
            System.out.println("签名验证失败...");
            return "error";
        }
    }
    //        for (String key:requestParams.keySet()){
    //            String value = request.getParameter(key);
    //            System.out.println("key: "+key+"=======>value"+value);
    //        }
    //        System.out.println("asyncVo:"+asyncVo);
    //        System.out.println("----------------------------");
    //        System.out.println("requestParams"+requestParams);
    //        return "success";
}
package com.saodai.saodaimall.order.vo;
import lombok.Data;
import lombok.ToString;
import java.util.Date;
/**
 * 支付的异步vo(用于下单付款后修改订单的状态为已付款)
 */
@ToString
@Data
public class PayAsyncVo {
    private String gmt_create;
    private String charset;
    private String gmt_payment;
    private Date notify_time;
    private String subject;
    private String sign;
    private String buyer_id;//支付者的id
    private String body;//订单的信息
    private String invoice_amount;//支付金额
    private String version;
    private String notify_id;//通知id
    private String fund_bill_list;
    private String notify_type;//通知类型; trade_status_sync
    private String out_trade_no;//订单号
    private String total_amount;//支付的总额
    private String trade_status;//交易状态  TRADE_SUCCESS
    private String trade_no;//流水号
    private String auth_app_id;//
    private String receipt_amount;//商家收到的款
    private String point_amount;//
    private String app_id;//应用id
    private String buyer_pay_amount;//最终支付的金额
    private String sign_type;//签名类型
    private String seller_id;//商家的id
}

(3)上面控制器的代码都是固定的,唯一是自己业务处理的代码就一句

唯一是自己业务处理:String result = orderService.handlePayResult(asyncVo);

  /**
     * 处理支付宝的支付结果(支付宝异步通知)
     * @param asyncVo
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String handlePayResult(PayAsyncVo asyncVo) {
        //保存交易流水信息
        PaymentInfoEntity paymentInfo = new PaymentInfoEntity();
        //订单号(对外业务号)
        paymentInfo.setOrderSn(asyncVo.getOut_trade_no());
        //支付宝交易流水号
        paymentInfo.setAlipayTradeNo(asyncVo.getTrade_no());
        //支付总金额
        paymentInfo.setTotalAmount(new BigDecimal(asyncVo.getBuyer_pay_amount()));
        //交易内容
        paymentInfo.setSubject(asyncVo.getBody());
        //支付状态
        paymentInfo.setPaymentStatus(asyncVo.getTrade_status());
        //创建时间
        paymentInfo.setCreateTime(new Date());
        //回调时间
        paymentInfo.setCallbackTime(asyncVo.getNotify_time());
        //添加到数据库中
        this.paymentInfoService.save(paymentInfo);
        //修改订单状态
        //获取当前状态 TRADE_SUCCESS
        String tradeStatus = asyncVo.getTrade_status();
        //TRADE_SUCCESS是支付宝提供的表示订单状态的常量(表示商家支持的可以退款的支付成功)TRADE_FINISHED表示商家不支持退款的支付成功
        if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
            //获取订单号(订单号是自己系统生成的订单号)
            String orderSn = asyncVo.getOut_trade_no();
            //orderSn是订单号 OrderStatusEnum.PAYED.getCode()是PAYED(1,"已付款")  PayConstant.ALIPAY支付类型
             this.updateOrderStatus(orderSn,OrderStatusEnum.PAYED.getCode(), PayConstant.ALIPAY);
        }
        return "success";
    }
    /**
     * 修改订单状态(其实就是把订单状态改成已付款)
     * @param orderSn  订单号
     * @param code  订单状态
     * @param payType  支付类型
     */
    private void updateOrderStatus(String orderSn, Integer code,Integer payType) {
        this.baseMapper.updateOrderStatus(orderSn,code,payType);
    }
<!--    修改订单状态-->
<update id="updateOrderStatus">
  UPDATE oms_order
  SET `status` = #{code},modify_time = NOW(),pay_type = #{payType},payment_time = NOW()
  WHERE order_sn = #{orderSn}
</update>
package com.saodai.saodaimall.order.entity;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
 * 保存交易流水信息
 */
@Data
@TableName("oms_payment_info")
public class PaymentInfoEntity implements Serializable {
  private static final long serialVersionUID = 1L;
  /**
   * id
   */
  @TableId
  private Long id;
  /**
   * 订单号(对外业务号)
   */
  private String orderSn;
  /**
   * 订单id
   */
  private Long orderId;
  /**
   * 支付宝交易流水号
   */
  private String alipayTradeNo;
  /**
   * 支付总金额
   */
  private BigDecimal totalAmount;
  /**
   * 交易内容
   */
  private String subject;
  /**
   * 支付状态
   */
  private String paymentStatus;
  /**
   * 创建时间
   */
  private Date createTime;
  /**
   * 确认时间
   */
  private Date confirmTime;
  /**
   * 回调内容
   */
  private String callbackContent;
  /**
   * 回调时间
   */
  private Date callbackTime;
}
目录
相关文章
|
7月前
|
前端开发 小程序 JavaScript
电商小程序04实现登录逻辑
电商小程序04实现登录逻辑
要会创建接口------支付系统19-------支付宝支付-----统一收单下单并支付页面接口----接口说明,接口文档中应该对如何调用接口进行一个详细的说明
要会创建接口------支付系统19-------支付宝支付-----统一收单下单并支付页面接口----接口说明,接口文档中应该对如何调用接口进行一个详细的说明
|
5月前
|
前端开发 API
支付系统27-------梳理一下支付按钮,前端的代码
支付系统27-------梳理一下支付按钮,前端的代码
|
5月前
|
存储 前端开发 Java
支付系统----微信支付17-----定义统一结果,返回时间格式不一样,怎样解决
支付系统----微信支付17-----定义统一结果,返回时间格式不一样,怎样解决
支付系统22------统一收单下单并支付页面接口-----调用支付宝接口,创建订单后期出现异常,能够打印出来的方法
支付系统22------统一收单下单并支付页面接口-----调用支付宝接口,创建订单后期出现异常,能够打印出来的方法
|
5月前
|
前端开发 Java
支付系统20-----支付宝支付-----统一收单下单并支付页面接口----定义controller,跨域注解,统一收单下单并支付页面接口的创建,打印日志的注解
支付系统20-----支付宝支付-----统一收单下单并支付页面接口----定义controller,跨域注解,统一收单下单并支付页面接口的创建,打印日志的注解
支付系统----微信支付16----创建案例项目-引入Swagger
支付系统----微信支付16----创建案例项目-引入Swagger
|
5月前
|
API 开发工具
支付系统26------支付宝支付-----接口参数设置总结
支付系统26------支付宝支付-----接口参数设置总结
|
7月前
|
移动开发 前端开发 程序员
支付功能在app中的实现及支付功能模块化调用流程图
支付功能在app中的实现及支付功能模块化调用流程图
57 0
|
缓存 NoSQL Redis
订单服务-----功能实现逻辑1
订单服务-----功能实现逻辑
92 0