【畅购商城】微信支付之支付模块

news2024/12/25 12:18:49

目录

支付页面

接口

后端实现

​​​​​​​前端实现​​​​​​​

​​​​​​​支付页面

步骤一:创建 flow3.vue组件

步骤二:引入第三方资源(js、css)

<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>

​​​​​​​接口

POST http://localhost:10010/order-service/pay
{
	"sn" : "1255513323915579400"
}

​​​​​​​后端实现

步骤一:编写 PayRequest,用于封装数据

package com.czxy.changgou4.vo;

import lombok.Data;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
public class PayRequest {
    private Long sn;
}

步骤二:检查order服务,yml文件中是否有微信配置

sc:
  pay:
    appID: wx8397f8696b538317
    mchID: 1473426802
    key: T6m9iK73b0kn9g5v426MKfHQH7X8rKwb
    httpConnectTimeoutMs: 5000
    httpReadTimeoutMs: 10000

步骤三:编写PayProperties,用于加载微信配置

package com.czxy.changgou4.config;

import com.github.wxpay.sdk.WXPayConfig;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.io.InputStream;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Data
@ConfigurationProperties(prefix = "sc.pay")
public class PayProperties implements WXPayConfig {

    private String appID;               // 公众账号ID

    private String mchID;               // 商户号

    private String key;                 // 生成签名的密钥

    private int httpConnectTimeoutMs;   // 连接超时时间

    private int httpReadTimeoutMs;      // 读取超时时间

    @Override
    public InputStream getCertStream() {
        //加载证书,需要通过账号中心生成
        return null;
    }

}

步骤四:编写PayState,自定义支付状态

package com.czxy.changgou4.utils;

import lombok.Getter;

/**
 * 自定义支付状态,微信支持多种状态,此处统一四种:
 * SUCCESS—支付成功、NOTPAY—未支付、CLOSED—已关闭、PAYERROR--支付失败
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Getter
public enum PayState {
    NOT_PAY(0,"未支付"),SUCCESS(1,"支付成功"),CLOSED(2,"已关闭"),PAY_ERROR(3,"支付失败");

    PayState(int code,String desc) {
        this.code = code;
        this.desc = desc;
    }
    private int code;           //自定义编码
    private String desc;        //描述信息
}

步骤五:编写PayHelper,用于微信操作的工具类

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;

    @Bean
    public WXPay wxPay(PayProperties payProperties){
        if(wxPay == null){
            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", "http://test.jingxi.com/wxpay/notify");
            // 交易类型为扫码支付
            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;
        }
    }
}

步骤五:编写PayService,调用工具类,用于生成支付接口

package com.czxy.changgou4.service;

import com.czxy.changgou4.vo.PayRequest;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
public interface PayService {

    public String pay(PayRequest payRequest);
}
package com.czxy.changgou4.service.impl;

import com.czxy.changgou4.service.PayService;
import com.czxy.changgou4.utils.PayHelper;
import com.czxy.changgou4.vo.PayRequest;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@Service
public class PayServiceImpl implements PayService {
    @Resource
    private PayHelper payHelper;

    @Override
    public String pay(PayRequest payRequest) {
        //根据sn查询订单
        //获得微信支付路径
        String payUrl = payHelper.createPayUrl(payRequest.getSn());
        //返回支付路径
        return payUrl;

    }
}

步骤六:编写PayController,根据sn生产微信支付路径

package com.czxy.changgou4.controller;

import com.czxy.changgou4.service.PayService;
import com.czxy.changgou4.vo.BaseResult;
import com.czxy.changgou4.vo.PayRequest;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * @author 桐叔
 * @email liangtong@itcast.cn
 */
@RestController
@RequestMapping("/pay")
public class PayController {

    @Resource
    private PayService payService;


    @PostMapping
    public BaseResult pay(@RequestBody PayRequest payRequest){
        //获得支付路径
        String payUrl = payService.pay(payRequest);
        //返回
        return BaseResult.ok("二维码生产成功").append("wxurl",payUrl);
    }

}

​​​​​​​前端实现

步骤一:修改apiclient.js文件,生成位置支付路径

  pay : ( params ) => {
    return axios.post("/order-service/pay" ,params )
  }

步骤二:拷贝qrcode.min.js 用于生成二维码

步骤三:导入qrcode.min.js

 script: [
      { type: 'text/javascript', src: '/js/qrcode.min.js' }
    ]

步骤四:页面加载成功,把微信支付路径生产二维码

  data() {
    return {
      sn: this.$route.query.sn,
    }
  },
  async mounted() {
    let {data} = await this.$request.pay({"sn":this.sn})
    new QRCode( document.getElementById("qrcode") , data.other.wxurl )
  },

步骤五:确定二维码生成的位置

<p>
   <div id="qrcode" style="width:256px;margin: 0 auto;"></div>
</p>

步骤六:优化,添加样式,

<style>
  #qrcode img {
    background-color: #fff;
    padding: 6px;
  }
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/71725.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[附源码]Python计算机毕业设计Django疫情物资管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

电动汽车 (BEV) 优化调度(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f389;作者研究&#xff1a;&#x1f3c5;&#x1f3c5;&#x1f3c5;本科计算机专业&#xff0c;研究生电气学硕…

Vue3中的pinia使用(收藏版)

1.pinia介绍 pinia 是 Vue 的存储库&#xff0c;它允许您跨组件/页面共享状态。就是和vuex一样的实现数据共享。 依据Pinia官方文档&#xff0c;Pinia是2019年由vue.js官方成员重新设计的新一代状态管理器&#xff0c;更替Vuex4成为Vuex5。 Pinia 目前也已经是 vue 官方正式的状…

原创 | 传统医药零售如何实现数字化转型

一、数字化转型是零售药店未来实现增长的必由之路“十四五”规划将清洁能源、军事、消费、医药以及高端制造等行业定为未来需要重点关注的领域。围绕“医保、医疗、医药”三条主线&#xff0c;医药行业推出了一系列重要的改革措施&#xff0c;即将进入有史以来最大变革的黄金时…

【Mysql 基础知识】

一、引言 #1.1 现有的数据存储方式有哪些&#xff1f; Java程序存储数据&#xff08;变量、对象、数组、集合&#xff09;&#xff0c;数据保存在内存中&#xff0c;属于瞬时状态存储。 文件&#xff08;File&#xff09;存储数据&#xff0c;保存在硬盘上&#xff0c;属于持久…

Talk | 香港大学在读博士生马逴凡:重新思考分辨率对于高效视频理解的意义

本期为TechBeat人工智能社区第460期线上Talk&#xff01; 北京时间12月7日(周三)20:00&#xff0c;香港大电子电机在读博士生——马逴凡的Talk将准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “重新思考分辨率对于高效视频理解的意义 ”&#xff0c;届时…

web课程设计:HTML非遗文化网页设计题材【京剧文化】HTML+CSS+JavaScript

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

12.8 - 每日一题 - 408

每日一句&#xff1a;成功与不成功之间有时距离很短只要后者再向前几步。 数据结构 1 若用冒泡排序方法对序列&#xff08;12&#xff0c;24&#xff0c;36&#xff0c;48&#xff0c;60&#xff0c;72&#xff09;从大到小排序&#xff0c;需要的比较次数是_____ A. 5 B. 1…

Tableau制作三元相图/三角图(Ternary/Triangle Chart)

三元相图 三角图就是有三个轴的坐标图&#xff0c;可以分别表示一个点在X、Y、Z三个维度上的不同比例情况。 与传统的XY坐标轴不同。XY坐标轴是有两个维度&#xff0c;而且每个维度没有上下限的限制。三角图中每个维度都在0-1的范围内&#xff0c;按百分比划分&#xff0c;即…

图像处理算法实战应用案例精讲-【目标检测】YOLO

前言 物体检测——顾名思义就是通过深度学习算法检测图像或视频中的物体。目标检测的目的是识别和定位场景中所有已知的目标。有了这种识别和定位,目标检测可以用来计数场景中的目标,确定和跟踪它们的精确位置,同时精确地标记它们。 目标检测通常与图像识别相混淆,所以在…

easyExcel 数据导入

前言 这段时间做了excel 数据导入&#xff0c;用的阿里巴巴的easyExcel 的代码。下面是官网和githab 代码地址。需要将github 上的代码拉下来&#xff0c;方便查看demo.关于Easyexcel | Easy ExcelEasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目&#xff0c;在尽…

[附源码]Python计算机毕业设计SSM基于与协同过滤算法的竞赛项目管理(程序+LW)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

可重复读实现原理

浅解释 概念 1、InnoDB 在每行记录后面保存两个隐藏的列&#xff0c;分别保存了数据行的创建版本号和删除版本号。每开始一个新的事务&#xff0c;系统版本号都会递增。事务开始时刻的系统版本号会作为事务的版本号&#xff0c;用来和查询到的每行记录的创建版本号对比。 2、i…

RKMEDIA--VP使用

本章描述rkmedia vp模块 即视频一入四处功能的介绍。 使用场景&#xff1a;主要用在DVR/DMS产品上&#xff0c;需要多路视频节点的输入和获取。 可以rv1126/rv1109可以外接模拟高清RX芯片&#xff08;NVP6188,TP2815等&#xff09;&#xff0c;达到8路camera输入的能力。 在…

PLSQL导出、导入数据 和 同步数据 以及 navicat 里同步数据 以及解决plsql导出数据乱码问题

PLSQL导出、导入数据 和 同步数据 以及 navicat 里同步数据 以及解决plsql导出数据乱码问题1. 导出数据1.1 导出.pde文件1.2 导出sql文件1.2.1 导出sql压缩文件1.2.1 导出问题——乱码 与 解决乱码问题1. 尝试解决方式12. 尝试解决方式23. 直接换PLSQ版本&#xff08;最终解决问…

Traysoft AddTapi.NET 支持多条线路

Traysoft AddTapi.NET 支持多条线路 使用Traysoft AddTapi。您可以轻松地将手机功能添加到C#、VB.NET和C应用程序中。添加Tapi。NET将为您提供开发移动应用程序所需的一切。包括&#xff1a;电话呼叫、接收者ID、语音邮件、警告系统、电话呼叫跟踪和监控。添加Tapi。NET继续联系…

微服务框架 SpringCloud微服务架构 25 黑马旅游案例 25.3 我附近的酒店

微服务框架 【SpringCloudRabbitMQDockerRedis搜索分布式&#xff0c;系统详解springcloud微服务技术栈课程|黑马程序员Java微服务】 SpringCloud微服务架构 文章目录微服务框架SpringCloud微服务架构25 黑马旅游案例25.3 我附近的酒店25.3.1 直接开干25 黑马旅游案例 25.3 …

计算机组成大题分析(四)

假设计算机 M 的主存地址为 24 位,按字节编址,采用分页存储管理方式,虚拟地址为 30 位,页大小为 4KB,TLB 采用 2 路组相联方式 和LRU 替换策略,一共8组。请回答一下问题。 (1) 虚拟地址中有哪几位表示虚页号? 哪几位表示内存地址? (2)己知访问 TLB 时虚页号高位部分用作 TLB…

留学Assignment写作语法错误怎么改正?

如何避免Assignment写作中的一些语法错误&#xff0c;在留学生提交论文要求进行润色修改时&#xff0c;经常会碰到一些语法上的错误&#xff0c;这都是英语水平的问题&#xff0c;同时也与自身的习惯相关&#xff0c;下面小编说一下Assignment写作的语法错误的几种情况&#xf…

浙江省AAA级“守合同重信用”公示企业

浙江省“守合同重信用”企业公示&#xff0c;是市场监管部门依企业自愿申请&#xff0c;对符合公示条件企业前两个年度内的合同履约信息向社会公示的行政指导行为。 浙江省“守合同重信用”企业公示实行逐级推荐、分级公示、动态管理制度。企业住所地县级市场监管局受理企业公示…