系统交互流程-订单支付-支付流程-JAVA实战演示

官网文档地址

官方文档地址:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_1
查询订单API: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_2
同一订单API: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
在线微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/index.html

微信支付流程

用户扫描商户展示在各种场景的二维码进行支付。

  • 商户根据微信支付的规则,生成不同的二维码,展示在各种场景,用于用户扫描购买。

  • 用户使用微信“扫一扫”,扫描二维码后,获取商品支付信息,引导用户完成支付。
    在这里插入图片描述

  • 用户确认支付,输入支付密码(如图6.4)。

  • 支付完成后会提示用户支付成功(如图6.5),商户后台得到支付成功的通知,然后进行发货处理。
    在这里插入图片描述

交互流程

在这里插入图片描述
业务流程说明:

(1)商户后台系统根据用户选购的商品生成订单。

(2)用户确认支付后调用微信支付【统一下单API】生成预支付交易;

(3)微信支付系统收到请求后生成预支付交易单,并返回交易会话的二维码链接code_url。

(4)商户后台系统根据返回的code_url生成二维码。

(5)用户打开微信“扫一扫”扫描二维码,微信客户端将扫码内容发送到微信支付系统。

(6)微信支付系统收到客户端请求,验证链接有效性后发起用户支付,要求用户授权。

(7)用户在微信客户端输入密码,确认支付后,微信客户端提交授权。

(8)微信支付系统根据用户授权完成支付交易。

(9)微信支付系统完成支付交易后给微信客户端返回交易结果,并将交易结果通过短信、微信消息提示用户。微信客户端展示支付交易结果页面。

(10)微信支付系统通过发送异步消息通知商户后台系统支付结果。商户后台系统需回复接收情况,通知微信后台系统不再发送该单的支付通知。

(11)未收到支付通知的情况,商户后台系统调用【查询订单API】。

(12)商户确认订单已支付后给用户发货。

微信支付账号和开发文档

微信支付的使用需要先在官网中进行账号的开通,获得商户的微信支付账号信息才可以使用。
朋友提供的测试用的商户号:

appid:微信公众账号或开放平台APP的唯一标识 wx8397f8696b538317
mch_id:商户号 1473426802
key:商户密钥 T6m9iK73b0kn9g5v426MKfHQH7X8rKwb

在具体微信支付商户信息后,需要进入官网查新微信支付平台的开发文档。
在线微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/index.html

请求参数如下,主要关注必填项目:
红色:支付渠道参数配置的内容
蓝色:微信sdk(开发工具包)自动配置
绿色:程序设置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

部署环境

打包SDK到本地仓库

进入SDK的项目目录,然后地址栏输入CMD,输入命令:
mvn source:jar install -Dmaven.test.skip=true
在这里插入图片描述

进入到本地仓库看到如图所示:那么恭喜你打包成功:

在这里插入图片描述

引入WXsdk依赖

在order-service中引入依赖

<dependency>
    <groupId>com.github.wxpay</groupId>
    <artifactId>wxpay-sdk</artifactId>
    <version>3.0.9</version>
</dependency>

添加配置

在订单微服务的application.yml增加微信支付

pay:
    wx:
      appID: wx8397f8696b538317
      mchID: 1473426802
      key: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
      payType: NATIVE
      notifyUrl: http://api.leyou.com/api/pay/wx/notify

定义配置类

@Configuration
public class PayConfiguration {

    @Bean
    @ConfigurationProperties(prefix = "pay.wx")
    public WXPayConfigImpl payConfig(){
        return new WXPayConfigImpl();
    }

    /**
     * 注册WXPay对象
     * @param payConfig 支付相关配置
     * @return WXPay对象
     * @throws Exception 连结WX失败时用到
     */
    @Bean
    public WXPay wxPay(WXPayConfigImpl payConfig) throws Exception {
        return new WXPay(payConfig);
    }
}

微信工具类

在订单微服务中定义微信生成二维码的工具类


@Component
@Slf4j
public class PayUtils {

    @Autowired
    private WXPay wxPay;

    @Autowired
    private WXPayConfigImpl payConfig;

    //构造二维码--订单号,总金额,商品名称
    public String createOrder(String orderNo, Long totalPay, String desc){

        Map<String, String> data = new HashMap<>();
        // 商品描述
        data.put("body", desc);
        // 订单号
        data.put("out_trade_no", orderNo);
        //金额,单位是分
        data.put("total_fee", totalPay.toString());
        //调用微信支付的终端IP
        data.put("spbill_create_ip", "127.0.0.1");
        //回调地址
        data.put("notify_url", payConfig.getNotifyUrl());
        // 交易类型为扫码支付
        data.put("trade_type", payConfig.getPayType());

        // 利用wxPay工具,完成下单
        Map<String, String> result = null;
        try {
            result = wxPay.unifiedOrder(data);
        } catch (Exception e) {
            log.error("【微信下单】创建预交易订单异常失败", e);
            throw new RuntimeException("微信下单失败", e);
        }
        // 校验业务状态
        String resultCode = result.get("result_code");
        if ("FAIL".equals(resultCode)) {
            log.error("【微信支付】微信支付业务失败,错误码:{},原因:{}", result.get("err_code"), result.get("err_code_des"));
            throw new RuntimeException("【微信支付】微信支付业务失败");
        }

        // 下单成功,获取支付链接
        String url = result.get("code_url");
        if (StringUtils.isBlank(url)) {
            throw new RuntimeException("微信下单失败,支付链接为空");
        }
        return url;
    }
}

实战演示

1.创建订单

Controller

@Slf4j
@RestController
@RequestMapping("/orders")
public class OrdersController {

    @Autowired
    private OrdersService  ordersService;

    /**
     *  创建订单
     *  地址:   POST  /create/{coursePubId}
     *  参数: coursePubId
     *  ResponseResult
     */
    @PostMapping("/create/{coursePubId}")
    public ResponseResult<String> create(@PathVariable("coursePubId") Long coursePubId) throws Exception {

        return ordersService.create(coursePubId);
    }

serviceIml

/**
 * 订单 服务实现类
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements OrdersService {

    @Autowired
    private SearchClient searchClient;

    //创建订单
    @Override
    public ResponseResult<String> create(Long coursePubId) throws Exception {
        //1、查询当前用户是否已经有已支付的订单数据
        Long userId = AuthInfoHolder.getUserId();
        LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Orders::getUserId, userId);//用户
        wrapper.eq(Orders::getCoursePubId, coursePubId);//课程发布id
        wrapper.eq(Orders::getStatus, OrdersConstants.PAID);//是否有已支付订单 1为已支付订单
        //1-1获取订单信息
        Orders orders = this.getOne(wrapper);
        //1-2 判断是否为空
        if (!StringUtils.isEmpty(orders)) {
            throw new BusinessException(ErrorCode.ORDERERROR);//已购买课程
        }

        //2、查询当前用户是否已经有已下单待支付的订单数据, 如果存在,返回
        LambdaQueryWrapper<Orders> qw = new LambdaQueryWrapper<>();
        qw.eq(Orders::getUserId, userId);//用户
        qw.eq(Orders::getCoursePubId, coursePubId);//课程发布id
        qw.eq(Orders::getStatus, OrdersConstants.ORDER_INIT_STATUS);//已下单未支付
        orders = this.getOne(qw);
        if (!StringUtils.isEmpty(orders)) {
            return ResponseResult.okResult(orders.getOrderNo());//返回订单号
        }

        //3、调用feign接口,查询当前课程的发布数据
        ResponseResult<CoursePubIndexVo> responseResult = searchClient.findById(coursePubId);
        CoursePubIndexVo vo = responseResult.getData();

        //4、构造Order对象,设置属性
        Orders ord = new Orders();
        ord.setOrderNo(UUID.randomUUID().toString(true));//订单编号
        ord.setCoursePubId(coursePubId);//课程发布id
        ord.setCoursePubName(vo.getName());//课程名
        ord.setCompanyId(vo.getCompanyId());//机构名
        ord.setCompanyName(vo.getCompanyName());//机构名
        ord.setUserId(AuthInfoHolder.getUserId());//用户id
        ord.setPrice(vo.getPrice().longValue());//价格一分
        ord.setStartTime(new Date());//开始时间
        ord.setEndTime(new Date());//结束时间
        ord.setStatus(OrdersConstants.ORDER_INIT_STATUS);//交易状态为初始状态
        ord.setCreateDate(new Date());//创建时间
        ord.setChangeDate(new Date());//修改时间

        //5、保存到数据库中
        boolean save = this.save(ord);
        if (!save) {
            throw new BusinessException(ErrorCode.PAYERROR);
        }
        //6.返回 订单号
        return ResponseResult.okResult(ord.getOrderNo());
    }

2.订单支付ServiceImpl -->返回给前端二维码

​1)当用户在支付页面中,选择某支付方式并确认时,前端向订单服务请求创建支付接口
2)订单服务 通过订单id获取要支付的订单信息,并将订单信息组装为第三方支付的下单请求数据,调用第三方支付服务下单。
​ 3)订单服务 接收第三方支付返回的支付二维码url,并将此url返回给前端
​ 4)前端将url生成为二维码,展示给用户

Controller

/**
 * 订单支付信息前端控制器
 */
@Slf4j
@RestController
@RequestMapping("/payment")
public class PaymentController {

    @Autowired
    private PaymentService  paymentService;
    /**
     *  构建支付连接  获取微信二维码
     * 地址: GET  /createPay
     * 参数:  Query:orderNo
     * 响应:  ResponseResult<string>
     */
    @GetMapping("/createPay")
    public ResponseResult<String> WXPay(String orderNo) {
        return paymentService.WXPay(orderNo);
    }
}

serviceImpl


/**
 * 订单支付信息 服务实现类
 */
@Service
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, Payment> implements PaymentService {

    @Autowired
    private OrdersService ordersService;
    @Autowired
    private PayUtils payUtils;

    /**
     * 创建支付信息 获取微信支付的二维码
     * 1.只能对已下单 未支付的订单创建支付信息
     * 2.支付信息只能存在一次
     */
    @Override
    public ResponseResult<String> WXPay(String orderNo) {
        //1.查询订单 判断订单的状态
        LambdaQueryWrapper<Orders> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Orders::getOrderNo, orderNo);//订单号
        Orders orders = ordersService.getOne(wrapper);
        if (orders.equals(OrdersConstants.ORDER_INIT_STATUS)) {
            throw new BusinessException(ErrorCode.PAYERROR);
        }

        //2.查询支付信息 判断是否已存在支付数据
        LambdaQueryWrapper<Payment> qw = new LambdaQueryWrapper<>();
        qw.eq(Payment::getOrderNo, orderNo);
        Payment payment = this.getOne(qw);//支付信息
        //3.构造支付数据 存入数据库
        if (StringUtils.isEmpty(payment)) {
            //3-1构建支付对象  设置参数
            payment  = new Payment();
            payment.setUserId(AuthInfoHolder.getUserId());//用户id
            payment.setCompanyId(orders.getCompanyId());//机构id
            payment.setOrderNo(orderNo);//订单编号
            payment.setStatus(OrdersConstants.NOT_PAID.toString());//未支付状态
            payment.setPayMethod(OrdersConstants.PAY_METHOD_WX);//支付方式 微信支付
            payment.setPayDate(new Date());//支付时间
            payment.setTotalAmount(orders.getPrice());//订单总金额
            payment.setReceiptAmount(orders.getPrice());//实收金额
            payment.setBuyerPayAmount(orders.getPrice());//付款金额
            payment.setCreateDate(new Date());//创建时间

            //保存支付信息
            boolean save = this.save(payment);
            if (!save) {
                throw new BusinessException(ErrorCode.PAYERROR);
            }
        }
        //4.调用微信工具类 生成支付二维码
        String url = payUtils.createOrder(payment.getOrderNo(),
                                            payment.getTotalAmount(),
                                            orders.getCoursePubName());
        //5.返回
        return ResponseResult.okResult(url);
    }
}

  • 4
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

上官玺

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值