前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【畅购商城】微信支付之支付回调和支付状态

【畅购商城】微信支付之支付回调和支付状态

作者头像
陶然同学
发布2023-02-24 13:20:28
9390
发布2023-02-24 13:20:28
举报
文章被收录于专栏:陶然同学博客

目录

Nuxt.js IP 启动

支付回调

回调接口

后端实现

查看支付状态

后端实现

​​​​​​​前端实现

​​​​​​​前置技术:RabbitMQ

​​​​​​​更新订单状态

​​​​​​​Nuxt.js IP 启动

代码语言:javascript
复制
  "config": {
    "nuxt": {
      "host": "0.0.0.0",
      "port": "3000"
    }
  },

​​​​​​​支付回调

​​​​​​​回调接口

步骤一:修改yml文件,添加notifyUrl配置

步骤二:修改配置文件

步骤三:修改工具类

步骤一:修改yml文件,添加notifyUrl配置

代码语言:javascript
复制
sc:
  pay:
    notifyUrl: http://40m459492i.wicp.vip/order-service/pay/callback

步骤二:修改配置文件

代码语言:javascript
复制
private String notifyUrl;           //回调路径

步骤三:修改工具类

代码语言:javascript
复制
package com.czxy.changgou4.utils;

import com.czxy.changgou4.config.PayProperties;
import com.github.wxpay.sdk.WXPay;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Component
@EnableConfigurationProperties(PayProperties.class)
public class PayHelper {

    private WXPay wxPay;
    private PayProperties payProperties;

    @Bean
    public WXPay wxPay(PayProperties payProperties){
        if(wxPay == null){
            this.payProperties = payProperties;
            wxPay = new WXPay(payProperties);
        }
        return wxPay;
    }

    private static final Logger logger = LoggerFactory.getLogger(PayHelper.class);

    public PayHelper() {

    }

    public PayHelper(PayProperties payProperties) {
        wxPay = new WXPay(payProperties);
    }

    public String createPayUrl(Long sn) {
        String key = "pay.url." + sn;

        try {
            Map<String, String> data = new HashMap<>();
            // 商品描述
            data.put("body", "商城测试");
            // 订单号
            data.put("out_trade_no", sn.toString());
            //货币
            data.put("fee_type", "CNY");
            //金额,单位是分
            data.put("total_fee", "1");
            //调用微信支付的终端IP(商城的IP)
            data.put("spbill_create_ip", "127.0.0.1");
            //回调地址
            data.put("notify_url", this.payProperties.getNotifyUrl());
            // 交易类型为扫码支付
            data.put("trade_type", "NATIVE");
            //商品id,使用假数据
            data.put("product_id", "1234567");

            Map<String, String> result = this.wxPay.unifiedOrder(data);
            if ("SUCCESS".equals(result.get("return_code"))) {
                if("SUCCESS".equals(result.get("result_code"))){
                    String url = result.get("code_url");

                    return url;
                } else {
                    logger.error("创建预交易订单失败,错误信息:{}", result.get("err_code_des"));
                    return null;
                }
            } else {
                logger.error("创建预交易订单失败,错误信息:{}", result.get("return_msg"));
                return null;
            }
        } catch (Exception e) {
            logger.error("创建预交易订单异常", e);
            return null;
        }
    }

    /**
     * 查询订单状态
     * 交易状态参考:(trade_state)
     SUCCESS—支付成功
     REFUND—转入退款
     NOTPAY—未支付
     CLOSED—已关闭
     REVOKED—已撤销(付款码支付)
     USERPAYING--用户支付中(付款码支付)
     PAYERROR--支付失败(其他原因,如银行返回失败)
     * @param sn
     * @return
     */
    public PayState queryOrder(Long sn) {
        Map<String, String> data = new HashMap<>();
        // 订单号
        data.put("out_trade_no", sn.toString());
        try {
            Map<String, String> result = this.wxPay.orderQuery(data);
            if("SUCCESS".equals(result.get("return_code"))){
                if("SUCCESS".equals(result.get("result_code"))) {
                    String tradeState = result.get("trade_state");
                    if ("SUCCESS".equals(tradeState)) {
                        return PayState.SUCCESS;
                    }
                    if ("NOTPAY".equals(tradeState)) {
                        return PayState.NOT_PAY;
                    }
                    if ("CLOSED".equals(tradeState)) {
                        return PayState.CLOSED;
                    }
                }
            }
            return PayState.PAY_ERROR;
        } catch (Exception e) {
            logger.error("查询订单状态异常", e);
            return PayState.PAY_ERROR;
        }
    }
}

​​​​​​​后端实现

  1. 步骤一:修改PayController,添加callback方法
  2. 步骤二:检查网关,放行callback方法
  3. 步骤三:修改花生壳,访问10010端口
代码语言:javascript
复制
https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_7&index=8

步骤一:修改PayController,添加callback方法

代码语言:javascript
复制
@PostMapping("/callback")
public void callback(HttpServletRequest request, HttpServletResponse response) throws IOException {
    try {
        //1 获得响应内容
        String xml = IOUtils.toString(request.getInputStream(), "UTF-8");
        System.out.println(xml);
        //解析
        Map<String, String> map = WXPayUtil.xmlToMap( xml );

        // 查询成功
        if("SUCCESS".equals(map.get( "result_code" )  )){

            // 获得订单号
            String sn = map.get("out_trade_no");

            //TODO  更新订单状态
            System.out.println(sn);

            //如果成功,给微信支付一个成功的响应
            response.setContentType("text/xml");
            String data = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
            response.getWriter().write(data);
        }

    } catch (Exception e) {
        e.printStackTrace();
        response.setContentType("text/xml");
        String data = "<xml><return_code><![CDATA[FAIL]]></return_code><return_msg><![CDATA["+e.getMessage()+"]]></return_msg></xml>";
        response.getWriter().write(data);
    }
}

步骤二:检查网关,放行callback方法

步骤三:修改花生壳,访问10010端口

查看控制台结果

代码语言:javascript
复制
<xml><appid><![CDATA[wx8397f8696b538317]]></appid>
<bank_type><![CDATA[COMM_CREDIT]]></bank_type>
<cash_fee><![CDATA[1]]></cash_fee>
<fee_type><![CDATA[CNY]]></fee_type>
<is_subscribe><![CDATA[N]]></is_subscribe>
<mch_id><![CDATA[1473426802]]></mch_id>
<nonce_str><![CDATA[47e529ea929e4c9e847ee9699751a648]]></nonce_str>
<openid><![CDATA[oNpSGwZaaw_0uBEMwFpkwIwFsttw]]></openid>
<out_trade_no><![CDATA[1259484402174529500]]></out_trade_no>
<result_code><![CDATA[SUCCESS]]></result_code>
<return_code><![CDATA[SUCCESS]]></return_code>
<sign><![CDATA[2D4BC610795C1DC303B0B26092D6C6E3]]></sign>
<time_end><![CDATA[20200510220429]]></time_end>
<total_fee>1</total_fee>
<trade_type><![CDATA[NATIVE]]></trade_type>
<transaction_id><![CDATA[4200000568202005108477965385]]></transaction_id>
</xml>
1259484402174529500

​​​​​​​查看支付状态

​​​​​​​后端实现

  1. 步骤一:修改PayService,查询订单支付状态
  2. 步骤二:编写PayService实现类
  3. 步骤三:修改PayController

步骤一:修改PayService,查询订单支付状态

代码语言:javascript
复制
package com.czxy.changgou4.service;

import com.czxy.changgou4.utils.PayState;
import com.czxy.changgou4.vo.PayRequest;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface PayService {
    /**
     * 查看支付状态
     * @param sn
     * @return
     */
    public PayState query(Long sn);
}

步骤二:编写PayService实现类

代码语言:javascript
复制
@Override
public PayState query(Long sn) {
    //查询微信支付状态
    PayState payState = payHelper.queryOrder(sn);
    return payState;

}

步骤三:修改PayController

代码语言:javascript
复制
@GetMapping("/{sn}")
public BaseResult query(@PathVariable("sn") Long sn){
    //查询
    PayState payState = payService.query(sn);
    //返回
    if(payState.getCode() == 1) {
        return BaseResult.ok(payState.getDesc());
    }
    return BaseResult.error(payState.getDesc());
}

​​​​​​​前端实现

如果订单已经支付,跳转到支付成功页面。

  1. 步骤一:修改api.js,查询订单支付状态
  2. 步骤二:修改flow3,“查询订单状态”绑定事件
  3. 步骤三:修改flow3,编写事件,如果是成功,调到到flow4
  4. 步骤四:编写flow4,与flow3基本内容一致,提示信息为“支付成功,货物即将送出!”

步骤一:修改api.js,查询订单支付状态

代码语言:javascript
复制
  findPayStatus : ( sn ) => {
    return axios.get("/order-service/pay/"+sn )
  }

步骤二:修改flow3,“查询订单状态”绑定事件

步骤三:修改flow3,编写事件,如果是成功,调到到flow4

代码语言:javascript
复制
  methods: {
    async findPayStatusFn() {
      let { data } = await this.$request.findPayStatus( this.sn );
      if( data.code == 20000) {
        location.href = 'flow4'
      } else {
        alert( data.message );
      }
    }
  },

步骤四:编写flow4,与flow3基本内容一致,提示信息为“支付成功,货物即将送出!”

代码语言:javascript
复制
<template>
  <div>
    <!-- 顶部导航 start -->
    <div class="topnav">
      <div class="topnav_bd w990 bc">
        <div class="topnav_left">

        </div>
        <div class="topnav_right fr">
          <ul>
            <li>您好,欢迎来到畅购![<a href="login.html">登录</a>] [<a href="register.html">免费注册</a>] </li>
            <li class="line">|</li>
            <li>我的订单</li>
            <li class="line">|</li>
            <li>客户服务</li>

          </ul>
        </div>
      </div>
    </div>
    <!-- 顶部导航 end -->

    <div style="clear:both;"></div>

    <!-- 页面头部 start -->
    <div class="header w990 bc mt15">
      <div class="logo w990">
        <h2 class="fl"><a href="index.html"><img src="images/logo.png" alt="畅购商城"></a></h2>
        <div class="flow fr flow3">
          <ul>
            <li>1.我的购物车</li>
            <li>2.填写核对订单信息</li>
            <li class="cur">3.成功提交订单</li>
          </ul>
        </div>
      </div>
    </div>
    <!-- 页面头部 end -->

    <div style="clear:both;"></div>

    <!-- 主体部分 start -->
    <div class="success w990 bc mt15">
      <div class="success_hd">
        <h2>订单支付成功</h2>
      </div>
      <div class="success_bd">
        <p><span></span>支付成功,货物即将送出!</p>
      </div>
    </div>
    <!-- 主体部分 end -->

    <div style="clear:both;"></div>
    <!-- 底部版权 start -->
    <Footer></Footer>
    <!-- 底部版权 end -->
  </div>
</template>

<script>
import TopNav from '../components/TopNav'
import Footer from '../components/Footer'

export default {
  head: {
    title: '首页',
    link: [
      {rel:'stylesheet',href: '/style/success.css'},
    ],
    script: [
    ]
  },
  components: {
    TopNav,
    Footer,
  }

}
</script>

<style>

</style>

​​​​​​​前置技术:RabbitMQ

​​​​​​​更新订单状态

步骤一:配置环境,

rabbitmq中添加order_pay队列

添加依赖

添加yml配置

步骤二:修改回调函数,将sn存放到rabbit中

步骤三:编写监听器(消费者),更新订单状态

步骤四:修改OrderService,完成修改功能

步骤五:修改OrderMapper,完成修改功能

步骤一:配置环境,

rabbitmq中添加order_pay队列,添加rabbit配置类

代码语言:javascript
复制
ackage com.czxy.changgou4.config;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Component
public class OrderPayQueue {

    private static final String ORDER_PAY_QUEUE = "order_pay";

    @Bean
    public Queue queue() {
        return new Queue(ORDER_PAY_QUEUE);
    }
}

添加依赖

代码语言:javascript
复制
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
</dependency>

 ​​​​​​​

添加yml配置

代码语言:javascript
复制
spring:
  rabbitmq:
    host: 127.0.0.1
    username: guest
    password: guest

步骤二:修改回调函数,将sn存放到rabbit中

rabbitTemplate.convertAndSend("", "order_pay", sn);

步骤三:编写监听器(消费者),更新订单状态

代码语言:javascript
复制
package com.czxy.changgou4.listener;

import com.czxy.changgou4.service.OrderService;
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;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Component
@RabbitListener(queues = "order_pay")
public class OrderPayListener {

    @Autowired
    private OrderService orderService;

    /**
     * 更新支付状态
     * @param message
     */
    @RabbitHandler
    public void updatePayStatus(String message){
        orderService.updatePayStatus( message , "1" );
    }
}

步骤四:修改OrderService,完成修改功能

代码语言:javascript
复制
package com.czxy.changgou4.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.czxy.changgou4.pojo.Order;
import com.czxy.changgou4.pojo.User;
import com.czxy.changgou4.vo.CartVo;
import com.czxy.changgou4.vo.OrderVo;

import java.util.List;

public interface OrderService extends IService<Order> {

    void updatePayStatus(String sn, String status);
}
代码语言:javascript
复制
package com.czxy.changgou4.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.czxy.changgou4.pojo.Order;
import com.czxy.changgou4.pojo.OrderGoods;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;

@Service
@Transactional
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Override
    public void updatePayStatus(String sn, String status) {
        //更新状态
        baseMapper.updateStatus(sn,status);
    }
}

步骤五:修改OrderMapper,完成修改功能  

代码语言:javascript
复制
package com.czxy.changgou4.mapper;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.czxy.changgou4.pojo.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Update;

@Mapper
public interface OrderMapper extends BaseMapper<Order> {
    /**
     * 更加sn修改状态
     * @param sn
     * @param status
     */
    @Update("UPDATE tb_order SET STATUS = #{status} WHERE sn = #{sn}")
    void updateStatus(@Param("sn") String sn, @Param("status") String status);
}

测试:在rabbitMQ web控制台,可以手动发布消息

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-12-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • ​​​​​​​Nuxt.js IP 启动
  • ​​​​​​​支付回调
    • ​​​​​​​回调接口
      • ​​​​​​​后端实现
      • ​​​​​​​查看支付状态
        • ​​​​​​​后端实现
          • ​​​​​​​前端实现
          • ​​​​​​​前置技术:RabbitMQ
          • ​​​​​​​更新订单状态
          相关产品与服务
          云支付
          云支付(Cloud Pay,CPay)为您提供开放、可靠的聚合收款技术服务和商户管理功能。云支付支持刷卡支付、扫码支付、一码多付多种支付方式。服务商也可使用云支付提供的 SDK 和 HTTPS 接口,将云支付集成进自己的系统中,为商户提供的个性化解决方案。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档