zoukankan      html  css  js  c++  java
  • 微信扫码支付3-生成支付二维码并支付

    一、准备

    1、添加微信支付SDK

    方式一:

    service_trade中添加依赖:

    <dependencies>
        <!--微信支付-->
        <dependency>
            <groupId>com.github.wxpay</groupId>
            <artifactId>wxpay-sdk</artifactId>
            <version>0.0.3</version>
        </dependency>
    </dependencies>
    

    方式二:
    将下载的sdk源码放入service_trade源码目录中
    BwG7gx.png

    2、配置yml参数

    支付账户相关参数:https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=3_1

    weixin:
      pay:
        #关联的公众号appid
        appId: wxf913bfa3a2c7eeeb
        #商户号
        partner: 1543338551
        #商户key
        partnerKey: atguigu3b0kn9g5v426MKfHQH7X8rKwb
        #回调地址
        notifyUrl: http://imhelen.free.idcfengye.com/api/trade/weixin-pay/callback/notify 
    

    配置后启动ngrok内网穿透工具

    3、参数读取工具类

    package com.atguigu.guli.service.trade.util;
    @Data
    @Component
    @ConfigurationProperties(prefix="weixin.pay")
    public class WeixinPayProperties {
        private String appId;
        private String partner;
        private String partnerKey;
        private String notifyUrl;
    }
    

    4、辅助业务方法

    OrderService:getOrderByOrderNo 根据订单号查询订单
    接口:

    Order getOrderByOrderNo(String orderNo);
    

    实现:

    public Order getOrderByOrderNo(String orderNo) {
    
        QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("order_no", orderNo);
        return baseMapper.selectOne(queryWrapper);
    }
    

    二、生成支付二维码

    1、统一下单接口文档

    https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=9_1
    调用统一下单接口,根据返回值中的code_url在前端使用javascript工具生成支付二维码

    2、业务层

    接口:创建 WeixinPayService:createNative

    package com.atguigu.guli.service.order.service;
    public interface WeixinPayService {
        Map<String, Object> createNative(String orderNo, String remoteAddr);
    }
    

    实现:

    package com.atguigu.guli.service.trade.service.impl;
    
    @Service
    @Slf4j
    public class WeixinPayServiceImpl implements WeixinPayService {
    
        @Autowired
        private OrderService orderService;
        
        @Autowired
        private WeixinPayProperties weixinPayProperties;
        
        @Override
        public Map<String, Object> createNative(String orderNo, String remoteAddr) {
            try{
                //根据课程订单号获取订单
                Order order = orderService.getOrderByOrderNo(orderNo);
        
                //调用微信api接口:统一下单(支付订单)
                HttpClientUtils client = new HttpClientUtils("https://api.mch.weixin.qq.com/pay/unifiedorder");
                //组装接口参数
                Map<String, String> params = new HashMap<>();
                params.put("appid", weixinPayProperties.getAppId());//关联的公众号的appid
                params.put("mch_id", weixinPayProperties.getPartner());//商户号
                params.put("nonce_str", WXPayUtil.generateNonceStr());//生成随机字符串
                params.put("body", order.getCourseTitle());
                params.put("out_trade_no", orderNo);
        
                //注意,这里必须使用字符串类型的参数(总金额:分)
                String totalFee = order.getTotalFee().intValue() + "";
                params.put("total_fee", totalFee);
        
                params.put("spbill_create_ip", remoteAddr);
                params.put("notify_url", weixinPayProperties.getNotifyUrl());
                params.put("trade_type", "NATIVE");
        
                //将参数转换成xml字符串格式:生成带有签名的xml格式字符串
                String xmlParams = WXPayUtil.generateSignedXml(params, weixinPayProperties.getPartnerKey());
                log.info("
     xmlParams:
    " + xmlParams);
        
                client.setXmlParam(xmlParams);//将参数放入请求对象的方法体
                client.setHttps(true);//使用https形式发送
                client.post();//发送请求
                String resultXml = client.getContent();//得到响应结果
                log.info("
     resultXml:
    " + resultXml);
                //将xml响应结果转成map对象
                Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
        
                //错误处理
                if("FAIL".equals(resultMap.get("return_code")) || "FAIL".equals(resultMap.get("result_code"))){
                    log.error("微信支付统一下单错误 - "
                            + "return_code: " + resultMap.get("return_code")
                            + "return_msg: " + resultMap.get("return_msg")
                            + "result_code: " + resultMap.get("result_code")
                            + "err_code: " + resultMap.get("err_code")
                            + "err_code_des: " + resultMap.get("err_code_des"));
        
                    throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
                }
        
                //组装需要的内容
                Map<String, Object> map = new HashMap<>();
                map.put("result_code", resultMap.get("result_code"));//响应码
                map.put("code_url", resultMap.get("code_url"));//生成二维码的url
                map.put("course_id", order.getCourseId());//课程id
                map.put("total_fee", order.getTotalFee());//订单总金额
                map.put("out_trade_no", orderNo);//订单号
        
                return map;
        
            } catch (Exception e) {
                log.error(ExceptionUtils.getMessage(e));
                throw new GuliException(ResultCodeEnum.PAY_UNIFIEDORDER_ERROR);
            }
        }
    }
    
    

    3、web层

    创建 ApiWeixinPayController:createNative

    package com.atguigu.guli.service.trade.controller.api;
    
    @RestController
    @RequestMapping("/api/trade/weixin-pay")
    @Api(description = "网站微信支付")
    @CrossOrigin //跨域
    @Slf4j
    public class ApiWeixinPayController {
    
        @Autowired
        private WeixinPayService weixinPayService;
        
        @GetMapping("create-native/{orderNo}")
        public R createNative(@PathVariable String orderNo, HttpServletRequest request) {
            String remoteAddr = request.getRemoteAddr();
            Map map = weixinPayService.createNative(orderNo, remoteAddr);
            return R.ok().data(map);
        }
    }
    

    三、支付前端

    1、安装二维码生成器

    npm install vue-qriously@1.1.1
    

    2、配置插件

    创建 plugins/vue-qriously-plugin.js

    import Vue from 'vue'
    import VueQriously from 'vue-qriously'
    Vue.use(VueQriously)
    

    nuxt.config.js中配置

    plugins: [
        { src: '~/plugins/vue-qriously-plugin.js', ssr: true }
    ],
    

    3、api

    创建 api/pay.js

    import request from '~/utils/request'
    
    export default {
      createNative(orderNo) {
        return request({
          baseURL: 'http://localhost:8170',
          url: `/api/trade/weixin-pay/create-native/${orderNo}`,
          method: 'get'
        })
      }
    }
    

    4、订单页面

    html:

    <el-button :disabled="!agree" type="danger" @click="toPay()">去支付</el-button>
    

    脚本:

    methods: {
        toPay() {
            if (this.agree) {
                this.$router.push({ path: '/pay/' + this.order.orderNo })
            }
        }
    }
    

    5、支付页面

    创建pages/pay/_id.vue

    <template>
      <div class="cart py-container">
        <!--主内容-->
        <div class="checkout py-container  pay">
          <div class="checkout-tit" style=" 1050px; margin: 0 auto; padding: 10px 0;">
            <h4 class="fl tit-txt"><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/100 }}</em></span>
            <div class="clearfix"/>
          </div>
          <div class="checkout-steps">
            <div class="fl weixin">微信支付</div>
            <div class="fl sao">
              <div class="fl code">
                <!-- <img id="qrious" src="~/assets/img/erweima.png" alt=""> -->
                <qriously :value="payObj.code_url" :size="338"/>
              </div>
              <div style="color: red; text-align:center;">请使用微信扫一扫</div>  
            </div>
            <div class="clearfix"/>
            <!-- <p><a href="pay.html" target="_blank"> 其他支付方式</a></p> -->
          </div>
        </div>
    
      </div>
    </template>
    <script>
    import payApi from '~/api/pay'
    export default {
      async asyncData(page) {
        const response = await payApi.createNative(page.route.params.id)
        return {
          payObj: response.data
        }
      }
    
      // 在created中获取数据,报告Invalid prop: type check failed for prop "value".
      // created() {
      //   payApi.createNative(this.$route.params.id).then(response => {
      //     this.payObj = response.data
      //   })
      // }
    }
    </script>
    
  • 相关阅读:
    调用其他类的方法
    CString中 format、trimLeft和trimright、trim 和FindOneOf用法
    GetAsyncKeyState()& 0x8000
    C++打开剪切板,获取剪切板数据
    CString比较不区分大小写
    C++ string中find() 用法
    CString数组和CStringArray
    nested exception is java.io.FileNotFoundException: Could not open ServletContext resource
    SQLPlus获取oracle表操作SQL
    XShell实现服务器端文件的上传下载
  • 原文地址:https://www.cnblogs.com/smalldong/p/13909674.html
Copyright © 2011-2022 走看看