WeChat-Zahlungsfront- und -backend

1. Erstellen Sie einen Tabellenauszug, ein Zahlungsprotokoll und eine Bestelltabelle

# Host: localhost  (Version 5.7.19)
# Date: 2019-11-18 15:49:50
# Generator: MySQL-Front 6.1  (Build 1.26)


#
# Structure for table "t_order"
#

CREATE TABLE `t_order` (
  `id` char(19) NOT NULL DEFAULT '',
  `order_no` varchar(20) NOT NULL DEFAULT '' COMMENT '订单号',
  `course_id` varchar(19) NOT NULL DEFAULT '' COMMENT '课程id',
  `course_title` varchar(100) DEFAULT NULL COMMENT '课程名称',
  `course_cover` varchar(255) DEFAULT NULL COMMENT '课程封面',
  `teacher_name` varchar(20) DEFAULT NULL COMMENT '讲师名称',
  `member_id` varchar(19) NOT NULL DEFAULT '' COMMENT '会员id',
  `nickname` varchar(50) DEFAULT NULL COMMENT '会员昵称',
  `mobile` varchar(11) DEFAULT NULL COMMENT '会员手机',
  `total_fee` decimal(10,2) DEFAULT '0.01' COMMENT '订单金额(分)',
  `pay_type` tinyint(3) DEFAULT NULL COMMENT '支付类型(1:微信 2:支付宝)',
  `status` tinyint(3) DEFAULT NULL COMMENT '订单状态(0:未支付 1:已支付)',
  `is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_order_no` (`order_no`),
  KEY `idx_course_id` (`course_id`),
  KEY `idx_member_id` (`member_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单';

#
# Data for table "t_order"
#

INSERT INTO `t_order` VALUES ('1195693605513891841','1195693605555834880','18','Java精品课程','http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/06/866e9aca-b530-4f71-a690-72d4a4bfd1e7.jpg','晴天','1','小三1231','13700000001',1,NULL,0,0,'2019-11-16 21:22:25','2019-11-16 21:22:25'),('1195694200178118657','1195694200186507264','18','Java精品课程','http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/06/866e9aca-b530-4f71-a690-72d4a4bfd1e7.jpg','晴天','1','小三1231','13700000001',1,NULL,0,0,'2019-11-16 21:24:47','2019-11-16 21:24:47'),('1196264007411744769','1196264005255872512','1192252213659774977','java基础课程:test','https://guli-file-190513.oss-cn-beijing.aliyuncs.com/cover/default.gif','晴天','1','小三1231','13700000001',1,NULL,1,0,'2019-11-18 11:09:00','2019-11-18 11:10:14'),('1196265495278174209','1196265495273979904','18','Java精品课程','http://guli-file.oss-cn-beijing.aliyuncs.com/cover/2019/03/06/866e9aca-b530-4f71-a690-72d4a4bfd1e7.jpg','晴天','1','小三1231','13700000001',1,NULL,0,0,'2019-11-18 11:14:54','2019-11-18 11:14:54');

#
# Structure for table "t_pay_log"
#

CREATE TABLE `t_pay_log` (
  `id` char(19) NOT NULL DEFAULT '',
  `order_no` varchar(20) NOT NULL DEFAULT '' COMMENT '订单号',
  `pay_time` datetime DEFAULT NULL COMMENT '支付完成时间',
  `total_fee` decimal(10,2) DEFAULT '0.01' COMMENT '支付金额(分)',
  `transaction_id` varchar(30) DEFAULT NULL COMMENT '交易流水号',
  `trade_state` char(20) DEFAULT NULL COMMENT '交易状态',
  `pay_type` tinyint(3) NOT NULL DEFAULT '0' COMMENT '支付类型(1:微信 2:支付宝)',
  `attr` text COMMENT '其他属性',
  `is_deleted` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '逻辑删除 1(true)已删除, 0(false)未删除',
  `gmt_create` datetime NOT NULL COMMENT '创建时间',
  `gmt_modified` datetime NOT NULL COMMENT '更新时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_order_no` (`order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='支付日志表';

#
# Data for table "t_pay_log"
#

INSERT INTO `t_pay_log` VALUES ('1194498446013001730','1194498300579704832','2019-11-13 14:13:17',1,'4200000469201911130676624386','SUCCESS',1,'{\"transaction_id\":\"4200000469201911130676624386\",\"nonce_str\":\"2Lc23ILl231It53M\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CFT\",\"openid\":\"oNpSGwR-QGG5DaZtDkh2UZlsFDQE\",\"sign\":\"5404850AA3ED0E844DE104651477F07A\",\"return_msg\":\"OK\",\"fee_type\":\"CNY\",\"mch_id\":\"1473426802\",\"cash_fee\":\"1\",\"out_trade_no\":\"1194498300579704832\",\"cash_fee_type\":\"CNY\",\"appid\":\"wx8397f8696b538317\",\"total_fee\":\"1\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"NATIVE\",\"result_code\":\"SUCCESS\",\"attach\":\"\",\"time_end\":\"20191113141314\",\"is_subscribe\":\"N\",\"return_code\":\"SUCCESS\"}',0,'2019-11-13 14:13:17','2019-11-13 14:13:17'),('1195253787449430017','1195253049260314624','2019-11-15 16:14:44',1,'4200000454201911150981874895','SUCCESS',1,'{\"transaction_id\":\"4200000454201911150981874895\",\"nonce_str\":\"MAM5UM4Xhv1lItvO\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CFT\",\"openid\":\"oNpSGwR-QGG5DaZtDkh2UZlsFDQE\",\"sign\":\"7DBDCAF4A078B30BB3EF073E6A238C20\",\"return_msg\":\"OK\",\"fee_type\":\"CNY\",\"mch_id\":\"1473426802\",\"cash_fee\":\"1\",\"out_trade_no\":\"1195253049260314624\",\"cash_fee_type\":\"CNY\",\"appid\":\"wx8397f8696b538317\",\"total_fee\":\"1\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"NATIVE\",\"result_code\":\"SUCCESS\",\"attach\":\"\",\"time_end\":\"20191115161440\",\"is_subscribe\":\"N\",\"return_code\":\"SUCCESS\"}',0,'2019-11-15 16:14:44','2019-11-15 16:14:44'),('1196264321397342210','1196264005255872512','2019-11-18 11:10:14',1,'4200000453201911184025781554','SUCCESS',1,'{\"transaction_id\":\"4200000453201911184025781554\",\"nonce_str\":\"D1dHexCLIFIxAAg2\",\"trade_state\":\"SUCCESS\",\"bank_type\":\"CFT\",\"openid\":\"oNpSGwR-QGG5DaZtDkh2UZlsFDQE\",\"sign\":\"C9F5CA1EE49EA7891736D73BEB423962\",\"return_msg\":\"OK\",\"fee_type\":\"CNY\",\"mch_id\":\"1473426802\",\"cash_fee\":\"1\",\"out_trade_no\":\"1196264005255872512\",\"cash_fee_type\":\"CNY\",\"appid\":\"wx8397f8696b538317\",\"total_fee\":\"1\",\"trade_state_desc\":\"支付成功\",\"trade_type\":\"NATIVE\",\"result_code\":\"SUCCESS\",\"attach\":\"\",\"time_end\":\"20191118111011\",\"is_subscribe\":\"N\",\"return_code\":\"SUCCESS\"}',0,'2019-11-18 11:10:14','2019-11-18 11:10:14');

2. Benötigte Schnittstelle:

1“ Generieren Sie eine Bestellung und geben Sie die Bestellnummer der Bestellung zurück


import java.util.UUID;

/**
 * <p>
 * 订单 服务实现类
 * </p>
 *
 * @author zyk
 * @since 2023-05-28
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
    @Autowired
    EduClinent eduClinent;
    @Autowired
    UserClient userClient;

    //    生成订单
    @Override
    public R saveOrder(String courseId, String userId) {
//        通过远程调用获取用户信息
        UcenterMemberOrder userInfoOrder = userClient.getUserInfoOrder(userId);
//        通过远程调用获取课程信息
        CourseWebVoOrder courseInfoOrder = eduClinent.queryCourse(courseId);
        Order order=new Order();
        String orderNo = UUID.randomUUID().toString().substring(0,20);
        order.setOrderNo(orderNo);//订单号
        order.setCourseId(courseId); //课程id
        order.setCourseTitle(courseInfoOrder.getTitle());//价格
        order.setCourseCover(courseInfoOrder.getCover());//课程封面
        order.setTeacherName(courseInfoOrder.getTeacherName());//讲师名字
        order.setTotalFee(courseInfoOrder.getPrice());//价格
        order.setMemberId(userId);//用户id
        order.setMobile(userInfoOrder.getMobile());//用户手机号
        order.setNickname(userInfoOrder.getNickname());//用户名
        order.setStatus(0);  //订单状态(0:未支付 1:已支付)
        order.setPayType(1);  //支付类型 ,微信1
        baseMapper.insert(order);
        return R.ok().data("orderNo",orderNo);
    }
}

2" Generieren Sie gemäß der Bestellnummer einen WeChat-Zahlungs-QR-Code (geben Sie den Link des QR-Codes zurück, geben Sie ihn an das Frontend zurück, verarbeiten Sie ihn vom Frontend und zeigen Sie den QR-Code an).

 /**
     * 根据订单编号,生成支付二维码
     * @param orderNo
     * @return
     */
    @Override
    public Map  creatQrCode(String orderNo) {
        try {
//         1.根据订单编号查询订单信息
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("order_no", orderNo);
            Order order = orderService.getOne(queryWrapper);

//         2.使用map设置生成二维码需要的参数
            Map map = new HashMap();
            map.put("appid","wx74862e0dfcf69954"); //支付id
            map.put("mch_id", "1558950191"); //商户号
            map.put("nonce_str", WXPayUtil.generateNonceStr()); //生成随机的字符串,让每次生成的二维码不一样
            map.put("body", order.getCourseTitle()); //生成二维码的名字,会显示在微信扫码后的界面
            map.put("out_trade_no", orderNo); //二维码唯一的标识,只要不重复就行,这里是订单编号
            map.put("total_fee", order.getTotalFee().multiply(new BigDecimal("100")).longValue()+""); //支付金额
            map.put("spbill_create_ip", "127.0.0.1"); //进行支付的ip地址,实际项目使用项目的域名
            map.put("notify_url", "http://guli.shop/api/order/weixinPay/weixinNotify"); //支付后回调地址
            map.put("trade_type", "NATIVE"); //支付类型,NATIVE:知道价格,生成二维码

//         3.发送httpclient请求,(需要xml格式参数) 地址是微信支付的固定地址
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/unifiedorder");
            client.setXmlParam(WXPayUtil.generateSignedXml(map, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            client.setHttps(true);
            //执行post请求发送
            client.post();

//         4.得到返回结果,结果是xml格式的
            String xml = client.getContent();
            // 将结果转为map
            Map<String, String> map2 = WXPayUtil.xmlToMap(xml);
            System.out.println("生成二维码,返回的结果"+map2);
            // 最终返回数据的封装
            Map resultMap = new HashMap();
            resultMap.put("out_trade_no", orderNo);//订单编号
            resultMap.put("course_id", order.getCourseId()); //课程编号
            resultMap.put("total_fee", order.getTotalFee() + ""); // 价格
            resultMap.put("result_code", map2.get("result_code"));  //返回二维码状态码
            resultMap.put("code_url", map2.get("code_url"));        //二维码地址
            return  resultMap;
        } catch (Exception e) {
            e.printStackTrace();
            throw new GuLiExeception(20001, "生成二维码时发生错误");
        }
    }

3》Überprüfen Sie den Zahlungsstatus der Bestellung

    /**
     * 通过订单编号查询支付状态
     * @param orderNo
     * @return
     */
    @Override
    public Map<String, String> querypayStatus(String orderNo) {
        try {
            // 1.使用map设置生成二维码需要的参数
            Map m = new HashMap<>();
            m.put("appid", "wx74862e0dfcf69954");
            m.put("mch_id", "1558950191");
            m.put("nonce_str", WXPayUtil.generateNonceStr());
            m.put("out_trade_no", orderNo);//订单编号
            // 2.发送httpClient请求
            HttpClient client = new HttpClient("https://api.mch.weixin.qq.com/pay/orderquery");
            client.setXmlParam(WXPayUtil.generateSignedXml(m, "T6m9iK73b0kn9g5v426MKfHQH7X8rKwb"));
            client.setHttps(true);
            client.post();
            // 3.得到返回内容
            String xml = client.getContent();
            Map<String, String> map = WXPayUtil.xmlToMap(xml);
            System.out.println("查询订单支付状态接口返回:"+map);
            return map;
        } catch (Exception e) {
            e.printStackTrace();
            throw new GuLiExeception(20001, "在查询订单状态时发生异常");
        }
    }

/**
     * 在支付成功后,更新订单表订单状态、向支付记录表添加支付记录
     * @param map
     */
    @Override
    public void updateOrdersStatus(Map<String, String> map) {
        //从map获取订单号
        String orderNo =map.get("out_trade_no");
        //根据订单号查询订单信息
        QueryWrapper<Order> wrapper =new QueryWrapper<>();
        wrapper.eq("order_no",orderNo);
        Order order=orderService.getOne(wrapper);
        // 如果该订单已支付,则直接返回
        if(order.getStatus()==1)
        {
            return;
        }
        // 更新订单表订单状态
        order.setStatus(1);
        orderService.updateById(order);
        //向支付记录表中添加支付记录
        PayLog payLog =new PayLog();
        payLog.setOrderNo(orderNo);
        payLog.setPayTime(new Date());
        payLog.setPayType(1);//支付类型 1微信
        payLog.setTotalFee(order.getTotalFee());//总价格
        payLog.setAttr(JSONObject.toJSONString(map));//将其他属性存储到数据库

        baseMapper.insert(payLog);
    }

Regler 

    // 查询订单状态(是否支付成功)
    @GetMapping("queryPayStatus/{orderNo}")
    public R queryStatus(@PathVariable String orderNo) throws Exception {
        Map<String, String> map = baseService.querypayStatus(orderNo);
        //如果map返回值为空,那绝对是订单支付出错了
        if (map == null) {
            return R.error().message("订单支付出错了!");
        }
        //如果支付成功
        if (map.get("trade_state").equals("SUCCESS")) {
            //添加支付记录到支付日志表,更新订单表订单状态
            baseService.updateOrdersStatus(map);
            return R.ok().message("支付成功");
        }
        //如果未支付成功
        return R.ok().code(25000).message("支付中");
    }

4. Frontend    

Nachdem Sie auf die Schaltfläche „Zahlung“ geklickt haben, rufen Sie die Schnittstelle auf, die den QR-Code generiert, springen Sie zur Zahlungsseite und überprüfen Sie alle drei Sekunden die Schnittstelle „Zahlungsstatus“. Wenn die Zahlung erfolgreich ist, wird zur Schnittstelle „Kursdetails“ gesprungen. Wenn die Zahlung erfolgt ist in Bearbeitung, es wird nicht verarbeitet.

<template>
  <div class="Page Confirm">
    <div class="Title">
      <h1 class="fl f18">订单确认</h1>
      <img src="~/assets/img/cart_setp2.png" class="fr">
      <div class="clear"></div>
    </div>
    <form name="flowForm" id="flowForm" method="post" action="">
      <table class="GoodList">
        <tbody>
        <tr>
          <th class="name">商品</th>
          <th class="price">原价</th>
          <th class="priceNew">价格</th>
        </tr>
        </tbody>
        <tbody>
        <!-- <tr>
          <td colspan="3" class="Title red f18 fb"><p>限时折扣</p></td>
        </tr> -->
        <tr>
          <td colspan="3" class="teacher">讲师:{
   
   {order.teacherName}}</td>
        </tr>
        <tr class="good">
          <td class="name First">
            <a target="_blank" :href="'https://localhost:3000/course/'+order.courseId">
              <img :src="order.courseCover"></a>
            <div class="goodInfo">
              <input type="hidden" class="ids ids_14502" value="14502">
              <a target="_blank" :href="'https://localhost:3000/course/'+ order.courseId">{
   
   {order.courseTitle}}</a>
            </div>
          </td>
          <td class="price">
            <p>¥<strong>{
   
   {order.totalFee}}</strong></p>
            <!-- <span class="discName red">限时8折</span> -->
          </td>
          <td class="red priceNew Last">¥<strong>{
   
   {order.totalFee}}</strong></td>
        </tr>
        <tr>
          <td class="Billing tr" colspan="3">
            <div class="tr">
              <p>共 <strong class="red">1</strong> 件商品,合计<span
                class="red f20">¥<strong>{
   
   {order.totalFee}}</strong></span></p>
            </div>
          </td>
        </tr>
        </tbody>
      </table>
      <div class="Finish">
        <div class="fr" id="AgreeDiv">
          
          <label for="Agree"><p class="on"><input type="checkbox" checked="checked">我已阅读并同意<a href="javascript:" target="_blank">《谷粒学院购买协议》</a></p></label>
        </div>
        <div class="clear"></div>
        <div class="Main fl">
          <div class="fl">
            <a :href="'/course/'+order.courseId">返回课程详情页</a>
          </div>
          <div class="fr">
            <p>共 <strong class="red">1</strong> 件商品,合计<span class="red f20">¥<strong
              id="AllPrice">{
   
   {order.totalFee}}</strong></span></p>
          </div>
        </div>
        <input name="score" value="0" type="hidden" id="usedScore">
        <button class="fr redb" type="button" id="submitPay" @click="toPay()">去支付</button>
        <div class="clear"></div>
      </div>
    </form>
  </div>
</template>
      
<script>
import orders from '@/api/orders'
export default {
  data() {
      return {
        order:''
      }
    },
    //根据订单id获取订单信息
    //异步调用的方式
    asyncData({params, error}) {
        return orders.getOrderInfo(params.oid).then(response => {
            return {
                order: response.data.data.data
            }
        })
    },
    methods: {
        //点击去支付,跳转到支付页面
        toPay() {
        this.$router.push({path: '/pay/' + this.order.orderNo})
        }
    }
}
</script>
<template>
  <div class="cart py-container">
    <!--主内容-->
    <div class="checkout py-container  pay">
      <div class="checkout-tit">
        <h4 class="fl tit-txt"><span class="success-icon"></span><span class="success-info">订单提交成功,请您及时付款!订单号:{
   
   {payObj.out_trade_no}}</span>
        </h4>
        <span class="fr"><em class="sui-lead">应付金额:</em><em class="orange money">¥{
   
   {payObj.total_fee}}</em></span>
        <div class="clearfix"></div>
      </div>
      <div class="checkout-steps">
        <div class="fl weixin">微信支付</div>
        <div class="fl sao">
          <p class="red">请使用微信扫一扫。</p>
          <div class="fl code">
            <!-- <img id="qrious" src="~/assets/img/erweima.png" alt=""> -->
            <!-- <qriously value="weixin://wxpay/bizpayurl?pr=R7tnDpZ" :size="338"/> -->
            <qriously :value="payObj.code_url" :size="338"/>
            <div class="saosao">
              <p>请使用微信扫一扫</p>
              <p>扫描二维码支付</p>
            </div>

          </div>

        </div>
        <div class="clearfix"></div>
        <!-- <p><a href="pay.html" target="_blank">> 其他支付方式</a></p> -->
        
      </div>
    </div>
  </div>
</template>
<script>
import orders from '@/api/orders'

  export default {
    //根据订单id生成微信支付二维码
    asyncData({params, error}) {
      return orders.createNative(params.pid).then(response => {
        return {//异步请求需要return
           payObj: response.data.data
        }

      })
    },
    data() {
      return {
        timer: null,  // 定时器名称
        
      }
    },
    mounted() {
      //在页面渲染之后执行
      //每隔三秒,去查询一次支付状态
      this.timer1 = setInterval(() => {
        this.queryPayStatus(this.payObj.out_trade_no)
      }, 3000);
    },
    methods: {
      //查询支付状态的方法
      queryPayStatus(out_trade_no) {
        orders.queryPayStatus(out_trade_no).then(response => {
          if (response.data.success) {
              //如果支付成功,清除定时器
              clearInterval(this.timer1)
                this.$message({
                type: 'success',
                message: '支付成功!'
                })
             //跳转到课程详情页面观看视频
             this.$router.push({path: '/course/' + this.payObj.course_id})
          }
        })
      }
    }
  }
</script>

おすすめ

転載: blog.csdn.net/sharesb/article/details/130915121
おすすめ