java接入apiv3微信小程序支付(以java的eladmin框架为例)

2023-10-27

一、需要准备的资料

        1.小程序AppID

                如:wx2e56f5******

        2.商户号

                如:1641******

        3.商户API私钥路径什么是商户API证书?如何获取商户API证书? 获取文件如下图:

                如:

                本地路径:E:\Env\eladmin\cert\c2\apiclient_key.pem(本地部署写入绝对路径)

                服务器路径:/data/cert/eladmin/c2/apiclient_key.pem(服务器写入相对路径)

        4.商户证书序列号:登录商户平台【API安全】->【API证书】->【查看证书】,可查看商户API证书序列号。

                如:4F24D009CDBC89A**********************

        5.商户APIV3密钥:API v3密钥 - 通用规则 | 微信支付商户文档中心

                如:tYsmXJrIr*****************

                【商户平台】->【账户中心】->【API安全】的页面设置该密钥,请求才能通过微信支付的签名校验。密钥的长度为32个字节。

        6.商户平台证书路径

                如:

                本地路径:E:\Env\eladmin\cert\c2\apiclient_cert.pem(本地部署写入绝对路径)

                服务器路径:/data/cert/eladmin/c2/apiclient_cert.pem(服务器写入相对路径)

        7.商户平台证书路径p12

                如:

                本地路径:E:\Env\eladmin\cert\c2\apiclient_cert.p12(本地部署写入绝对路径)

                服务器路径:/data/cert/eladmin/c2/apiclient_cert.p12(服务器写入相对路径)

二、代码部分

1.pom.xml内加入微信支付扩展
    
<!--     微信支付   -->
    <dependency>
        <groupId>com.github.wechatpay-apiv3</groupId>
        <artifactId>wechatpay-java</artifactId>
        <version>0.2.7</version>
    </dependency>
2.在resources的dev和prod内加入微信支付必填字段
    #微信支付字段
    
      
wx:
      merchantId: 164*******
      privateKeyPath: E:\Env\eladmin\cert\c2\apiclient_key.pem
      certPath: E:\Env\eladmin\cert\c2\apiclient_cert.pem
      certP12Path: E:\Env\eladmin\cert\c2\apiclient_cert.p12
      merchantSerialNumber: 4F24D009CDBC**********************
      apiV3key: tYsmXJr******************
      appId: wx2e56f5******
3.微信支付测试接口
   3-1:测试下单接口
       /api/weChatPay/ceshiJSAPI
   3-2:测试微信支付结果回调地址,当微信支付后,微信方返回支付信息,在回调接口内触发业务逻辑
       注:测试回调接口必须为线上接口,线下无法实现
          可先在线上将微信返回数据打印到txt文件内,然后在本地测试回调接口,触发业务逻辑
       /api/weChatPay/ceshiPayNotify(放入线上的测试回调接口)
       /api/weChatPay/payNotify(本地测试回调接口)--可在postman内测试
       测试时,在Headers内Wechatpay-Serial、Wechatpay-Nonce、Wechatpay-Timestamp、Wechatpay-Signature必填上
       微信返回的json,直接放入postman软件的body内raw的json内进行测试
       
4.退款测试接口
   /api/weChatPay/ceshiRefund(回调接口不是必填项,可用可不用)
WeChatPayService.java:可放在Service内
----------------------------------------------------

package me.zhengjie.modules.api.service;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;
import java.util.Random;

@Service
@RequiredArgsConstructor
public class WeChatPayService {

    /** 商户API私钥路径 */
    @Value("${wx.privateKeyPath}") //可自己写死路径
    public  String privateKeyPath;

    //=============生成签名=====开始===================================================
    /**
     * 作用:使用字段appId、timeStamp、nonceStr、package计算得出的签名值
     * 场景:根据微信统一下单接口返回的 prepay_id 生成调启支付所需的签名值
     * @param appId
     * @param timestamp
     * @param nonceStr
     * @param pack package
     * @return
     * @throws Exception
     */
    public String getSign(String appId, long timestamp, String nonceStr, String pack) throws Exception{
        String message = buildMessage(appId, timestamp, nonceStr, pack);
        String paySign= sign(message.getBytes("utf-8"));
        return paySign;
    }

    private String buildMessage(String appId, long timestamp, String nonceStr, String pack) {
        return appId + "\n"
                + timestamp + "\n"
                + nonceStr + "\n"
                + pack + "\n";
    }

    private String sign(byte[] message) throws Exception{
        Signature sign = Signature.getInstance("SHA256withRSA");
        //这里需要一个PrivateKey类型的参数,就是商户的私钥。
        sign.initSign(getPrivateKey(privateKeyPath));
        sign.update(message);
        return Base64.getEncoder().encodeToString(sign.sign());
    }

    /**
     * 获取私钥。
     *
     * @param filename 私钥文件路径  (required)
     * @return 私钥对象
     */
    public static PrivateKey getPrivateKey(String filename) throws IOException {

        String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8");
        try {
            String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "")
                    .replace("-----END PRIVATE KEY-----", "")
                    .replaceAll("\\s+", "");

            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(
                    new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey)));
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    /**
     * 获取随机位数的字符串
     * @param length
     * @return
     */
    public static String getRandomString(int length) {
        String base = "abcdefghijklmnopqrstuvwxyz0123456789";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }
    //=============生成签名=====结束===================================================


    /**
     * 获取请求文体
     * @param request
     * @return
     * @throws IOException
     */
    public static String getRequestBody(HttpServletRequest request) throws IOException {
        ServletInputStream stream = null;
        BufferedReader reader = null;
        StringBuffer sb = new StringBuffer();
        try {
            stream = request.getInputStream();
            // 获取响应
            reader = new BufferedReader(new InputStreamReader(stream));
            String line;
            while ((line = reader.readLine()) != null) {
                sb.append(line);
            }
        } catch (IOException e) {
            throw new IOException("读取返回支付接口数据流出现异常!");
        } finally {
            reader.close();
        }
        return sb.toString();
    }
}
Controller代码如下:

package me.zhengjie.modules.api.rest;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.notification.NotificationConfig;
import com.wechat.pay.java.core.notification.NotificationParser;
import com.wechat.pay.java.core.notification.RequestParam;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.Amount;
import com.wechat.pay.java.service.payments.jsapi.model.Payer;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayRequest;
import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
import com.wechat.pay.java.service.payments.model.Transaction;
import com.wechat.pay.java.service.refund.RefundService;
import com.wechat.pay.java.service.refund.model.AmountReq;
import com.wechat.pay.java.service.refund.model.CreateRequest;
import com.wechat.pay.java.service.refund.model.Refund;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhengjie.annotation.AnonymousAccess;
import me.zhengjie.annotation.Log;
import me.zhengjie.config.FileProperties;
import me.zhengjie.exception.BadRequestException;
import me.zhengjie.modules.api.service.WeChatPayService;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequiredArgsConstructor
@Api(tags = "1.微信小程序")
@RequestMapping("/api/weChatPay")
public class WeChatPayContoller {

    private final WeChatPayService weChatPayService;
    private final FileProperties fileProperties;
    /**
     * appID
     */
    @Value("${wx.appId}") // 可自己写死--我引用的是自己写的配置内(写死的方式如:public String appId=wx12345678910)
    public String appId;

    /**
     * 商户号
     */
    @Value("${wx.merchantId}") // 可自己写死
    public String merchantId;

    /**
     * 商户API私钥路径
     */
    @Value("${wx.privateKeyPath}") //可自己写死
    public String privateKeyPath;

    /**
     * 商户证书序列号
     */
    @Value("${wx.merchantSerialNumber}") // 可自己写死
    public String merchantSerialNumber;

    /**
     * 商户APIV3密钥
     */
    @Value("${wx.apiV3key}") //可自己写死
    public String apiV3key;

    /**
     * 商户平台证书路径
     */
    @Value("${wx.certPath}") // 可自己写死
    public String certPath;

    /**
     * 商户平台证书路径p12
     */
    @Value("${wx.certP12Path}") //可自己写死
    public String certP12Path;


    private static Map<String, Config> configMap = new HashMap<>();

    private static Config config = null;
    private static JsapiService service = null;
    private static RefundService refundService = null;


    /**
     * JSAPI 测试下单接口
     */
    @PostMapping(value = "/ceshiJSAPI")
    @Log("JSAPI 测试下单接口")
    @ApiOperation("JSAPI 测试下单接口")
    @AnonymousAccess
    @Transactional(rollbackFor = Exception.class)
    public JSONObject ceshiJSAPI() throws Exception {
        if (config == null) {
            config =
                    new RSAAutoCertificateConfig.Builder()
                            .merchantId(merchantId)
                            .privateKeyFromPath(privateKeyPath)
                            .merchantSerialNumber(merchantSerialNumber)
                            .apiV3Key(apiV3key)
                            .build();
        }
        if (service == null) {
            service = new JsapiService.Builder().config(config).build();
        }
        // request.setXxx(val)设置所需参数,具体参数可见Request定义
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(1);//金额,1为0.01元
        request.setAmount(amount);
        request.setAppid(appId);
        request.setMchid(merchantId);
        request.setDescription("测试商品标题");//下单标题
        request.setNotifyUrl("https://www.ceshi123.com/api/weChatPay/ceshiPayNotify");//要求必须为线上接口
        String ddh = weChatPayService.getRandomString(20);
        request.setOutTradeNo(ddh);//订单号
        Payer payer = new Payer();
        payer.setOpenid("oMr**********");//openid
        request.setPayer(payer);
        PrepayResponse response = service.prepay(request);

        JSONObject result = new JSONObject();

        Long date = new Date().getTime();//获取当前时间戳
        String nonceStr = weChatPayService.getRandomString(28);//随机字符串,长度为32个字符以下

        result.put("timeStamp", date.toString());//时间戳
        result.put("nonceStr", nonceStr);//随机字符串,长度为32个字符以下
        result.put("package", "prepay_id=" + response.getPrepayId());//PrepayId
        result.put("signType", "RSA");//签名类型
        result.put("paySign", weChatPayService.getSign(appId, date, nonceStr, "prepay_id=" + response.getPrepayId()));//签名

        return result;
    }

    /**
     * 测试微信支付结果回调地址(放入线上测试)
     *
     * @param
     */
    @PostMapping(value = "/ceshiPayNotify")
    @Log("ceshiPayNotify方法")
    @ApiOperation("ceshiPayNotify方法")
    @AnonymousAccess
    public void ceshi_payNotify(HttpServletRequest request) throws IOException {
        //微信返回的证书序列号
        String serialNo = request.getHeader("Wechatpay-Serial");
        //微信返回的随机字符串
        String nonceStr = request.getHeader("Wechatpay-Nonce");
        //微信返回的时间戳
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        //微信返回的签名
        String wechatSign = request.getHeader("Wechatpay-Signature");
        String singType = request.getHeader("Wechatpay-Signature-Type");
        String collect = request.getReader().lines().collect(Collectors.joining());
        try {
            FileUtil.writeUtf8String(collect, fileProperties.getPath().getPath() + "/huidiao-collect.txt");//打印看效果
            FileUtil.writeUtf8String(serialNo, fileProperties.getPath().getPath() + "/huidiao-serialNo.txt");//打印看效果
            FileUtil.writeUtf8String(singType, fileProperties.getPath().getPath() + "/huidiao-Signature-Type.txt");//打印看效果
            FileUtil.writeUtf8String(nonceStr, fileProperties.getPath().getPath() + "/huidiao-nonceStr.txt");//打印看效果
            FileUtil.writeUtf8String(timestamp, fileProperties.getPath().getPath() + "/huidiao-timestamp.txt");//打印看效果
            FileUtil.writeUtf8String(wechatSign, fileProperties.getPath().getPath() + "/huidiao-wechatSign.txt");//打印看效果

            //TODO 业务校验---可以写入自己的业务逻辑

        } catch (Exception e) {
            System.out.println("e = " + e);
            FileUtil.writeUtf8String("22222222222222222222", fileProperties.getPath().getPath() + "/huidiao22.txt");//打印看效果
        }
    }

    /**
     * 微信支付结果回调地址(本地)
     *
     * @param request
     * @return
     */
    @PostMapping(value = "/payNotify")
    @AnonymousAccess
    @Transactional(rollbackFor = Exception.class)
    public ResponseEntity<Object> wxCallback(HttpServletRequest request) throws Exception {
        //获取报文
        String body = weChatPayService.getRequestBody(request);
        //随机串
        String nonce = request.getHeader("Wechatpay-Nonce");
        //微信传递过来的签名
        String signature = request.getHeader("Wechatpay-Signature");
        //证书序列号(微信平台)
        String wechatPaySerial = request.getHeader("Wechatpay-Serial");
        String singType = request.getHeader("Wechatpay-Signature-Type");
        //时间戳
        String timestamp = request.getHeader("Wechatpay-Timestamp");
        if (configMap.get("config") == null) {
            config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(merchantId)
                    .privateKeyFromPath(privateKeyPath)
                    .merchantSerialNumber(merchantSerialNumber)
                    .apiV3Key(apiV3key)
                    .build();
            configMap.put("config", config);
        }
        else {
            config = configMap.get("config");
        }
        NotificationParser parser = new NotificationParser((NotificationConfig) config);
        RequestParam.Builder builder = new RequestParam.Builder();
        builder.body(body);
        builder.signature(signature);
        builder.nonce(nonce);
        builder.timestamp(timestamp);
        builder.serialNumber(wechatPaySerial);
        builder.signType(singType);
        RequestParam requestParam = builder.build();

        Transaction parse = parser.parse(requestParam, Transaction.class);
        if ("SUCCESS".equals(parse.getTradeState().toString())) {
            //支付成功,你的业务逻辑

            return new ResponseEntity<>(HttpStatus.OK);

        } else {
            throw new BadRequestException( "支付失败");
        }
    }


    /** 测试退款申请
     * @return*/
    @PostMapping(value = "/ceshiRefund")
    @Log("JSAPI 测试退款接口")
    @ApiOperation("JSAPI 测试退款接口")
    @AnonymousAccess
    @Transactional(rollbackFor = Exception.class)
    public JSONObject ceshiRefund(String No) throws Exception {
        if (config == null) {
            config = new RSAAutoCertificateConfig.Builder()
                    .merchantId(merchantId)
                    .privateKeyFromPath(privateKeyPath)
                    .merchantSerialNumber(merchantSerialNumber)
                    .apiV3Key(apiV3key)
                    .build();
        }
        if (refundService == null) {
            // 初始化服务
            refundService = new RefundService.Builder().config(config).build();
        }
        CreateRequest request = new CreateRequest();
        request.setOutTradeNo(No);//商户订单号
        request.setOutRefundNo(weChatPayService.getRandomString(16));//商户退款单号,随机生成
        request.setReason("取消订单的退款");//退款原因
        AmountReq amount = new AmountReq();//金额信息
        amount.setRefund(Long.parseLong("1"));//退款金额(0.01元)
        amount.setTotal(Long.parseLong("1"));//原订单退款金额(0.01元)
        amount.setCurrency("CNY");//人民币
        request.setAmount(amount);

//        request.setNotifyUrl("https://https://www.ceshi123.com/api/weChatPay/ceshiRefundNotify");//回调接口,退款时非必填--这里我就没写接口

        JSONObject result = new JSONObject();
        try {
            Refund response = refundService.create(request);
            result.put("code", "SUCCESS");
            result.put("message", "退款成功");
            return result;
        } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
            // 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
            return JSONObject.parseObject(e.getResponseBody());
        }
    }

}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

java接入apiv3微信小程序支付(以java的eladmin框架为例) 的相关文章

  • 面试官:我就问了一个JVM性能调优,没想到他能吹半个小时

    一 JVM内存模型及垃圾收集算法 1 根据Java虚拟机规范 JVM将内存划分为 New 年轻代 Tenured 年老代 永久代 Perm 其中New和Tenured属于堆内存 堆内存会从JVM启动参数 Xmx 3G 指定的内存中分配 Pe
  • 迟来的函数传参补充——传引用【引用调用】【c++】

    文章目录 1 传引用 1 1 特点 1 2 使用 1 2 1 一般引用 1 2 2 常量引用 1 3 案例 1 3 1 常见变量引用做函数参数 1 3 2 结构体引用做函数参数 1 传引用 函数传参 几乎一直在用简单的值传递 或者传指针 前
  • Selenium浏览器自动化测试框架简单介绍

    目录 selenium简介 介绍 功能 优势 基本使用 获取单节点 获取多节点 节点交互 动作链 执行JavaScript代码 获取节点信息 切换frame 延时等待 前进和后退 cookies 选项卡管理 异常处理 选项卡切换 无头浏览器
  • Python--类及其方法

    Python 类及其方法 文章目录 Python 类及其方法 前言 一 类的定义 二 继承类定义 二 类的专业方法 前言 在 Python 中 面向对象编程主要有两个主题 就是类和类实例 类与实例 类与实例相互关联着 类是对象的定义 而实例
  • React怎样在非组件环境下拿到路由信息实现路由跳转

    最近写项目的时候遇到一个问题 如图所示 用户token失效后 页面需要跳转回登录页面 用location href直接赋值会导致页面刷新 对SPA来说是可耻的 而且location href跳转的时候 页面并没有提示信息出现就直接跳转了 然

随机推荐

  • 微信小程序——flex布局

    flex布局的基本知识 flex布局作用于父容器之上 用于控制其子盒子的位置和排列的方式 flex是Flexible Box的缩写 意为 弹性布局 用来为盒状模型提供最大的灵活性 任何一个容器都可以指定为Flex布局 box display
  • 应用层概述、基本原理

    网络应用体系结构 客户机 服务器结构 Client Server C S 点对点结构 peer to peer P2P 混合结构 Hybrid 1 客户机 服务器结构 服务器 7 24小时提供服务 永久性访问地址 域名 利用大量服务器实现可
  • aix安装bff_在AIX中安装与维护软件

    学习内容 在 AIX 中安装与维护软件 学习目标 1 了解安装软件包的含义及命名规则 2 了解 AIX 如何发布补丁 知道自己的 AIX 及已安装软件的版本情况 3 知道如何安装与管理软件及升级 4 会修复损坏的软件 5 知道如何通过 Fi
  • Linux/Windows中根据端口号关闭进程及关闭Java进程

    目录 Linux 根据端口号关闭进程 关闭Java服务进程 Windows 根据端口号关闭进程 Linux 根据端口号关闭进程 第一步 根据端口号查询进程PID 可使用如下命令 netstat anp grep 8088 以8088端口号为
  • java判空方式

    java判空方式 1 数据结构判空 map list set CollectionUtils isEmpty 为空 CollectionUtils isNotEmpty 不为空 2 对象判空 Objects isNull 为空 Object
  • IPv6你知道多少?

    IPv6是什么 互联网协议 IP 地址是分配给连接到互联网的每个设备的数字标识符 从广义上讲 IP地址允许设备相互通信并交换信息 Internet协议版本4 IPv4 于1983年发布 至今仍用于大多数Internet通信 IPv4地址使用
  • MongoDB.WebIDE:升级版的Mongodb管理工具

    很早以前收藏了一片文章 强大的MongoDB数据库管理工具 最近刚好要做一些MongoDB方面的工作 于是翻出来温习了一下 用起来也确实挺方便 不过在使用过程中出现了一些个问题 加上更喜欢MongoUVE的操作习惯 于是决定 自己动手 丰衣
  • Java之object和string的理解

    Java之object和string的理解 文章链接http blog csdn net qq 16628781 article details 65036244 知识点 栈区 堆区和方法区 object类clone 和qeuales 方法
  • dubbo之mock模拟

    1 写在前面 考虑这样的场景 当服务提供者还没有开发完毕或者是因为某些原因无法启动时 会导致服务消费者方的停滞 此时为了能够正常的开发测试 可以使用mock功能 在服务消费者端提供一个服务接口的mock实现类 来模拟调用服务提供者正常获取结
  • RCE高危漏洞预警:CVE-2021-40444简要分析

    漏洞影响及其危害 未经身份验证的攻击者可以利用该漏洞在目标系统上执行代码 Microsoft发布了一份关于此漏洞的官方公告 这篇博客文章讨论了该漏洞如何发挥作用 我们已获得多个利用此漏洞的文档样本 文档包中的document xml rel
  • JSONP 教程

    本章节我们将向大家介绍 JSONP 的知识 Jsonp JSON with Padding 是 json 的一种 使用模式 可以让网页从别的域名 网站 那获取资料 即跨域读取数据 为什么我们从不同的域 网站 访问数据需要一个特殊的技术 JS
  • CTFHUBWeb技能树——信息泄露writeup

    web之信息泄露 一 目录遍历 二 PHPINFO 三 备份文件下载 1 网站源码 2 bak文件 3 Vim缓存 4 DS Store 四 Git泄露 1 Log 2 Stash 3 Index 五 SVN泄露 六 HG泄露 一 目录遍历
  • 一口气用Python写了13个小游戏(附源码)

    今天给大家分享13个游戏源码 可以自己复现玩玩 研究下里面的编程逻辑 对学习编程 特别是初学者 应该会有很大帮助 1 吃金币 源码分享 import os import cfg import sys import pygame import
  • 做自媒体创作,这些坑你都踩过吗?快来避雷

    做自媒体以来 我经历过不少误区 走了很多弯路才觉悟出来 这里分享给大家 看看你有没有踩坑 1 不要把涨粉放在第一位 粉丝多少不是关键 20万粉丝的创作者我也有接触 几乎无变现能力 2 标题和封面的重要性 我以前愿意花几个小时写一篇文章 或者
  • nginx脚本

    将wget下载nginx 1 22 0 tar gz包 直接复制到文本中 添加执行权限 chmod 744 脚本名称 脚本名称或sh 脚本名称 执行脚本 bin bash shijian 20220717 xingming zs echo
  • Linux基础笔记

    文章目录 一 Linux目录结构 二 vi 和 vim 1 三种方式 2 基础操作 三 Linux基础命令 1 关机 重启 2 登录 注销 3 用户管理 4 运行级别 5 帮助指令 6 文件目录指令 7 压缩 解压 8 组管理 9 权限管理
  • Python大神给免费分享一个爬取12306火车票例子(附源码)

    上面是以前写的文章的资源 在以前的文章中有对应的资源 有兴趣的可以去查看 作为一种便捷地收集网上信息并从中抽取出可用信息的方式 网络爬虫技术变得越来越有用 使用Python这样的简单编程语言 你可以使用少量编程技能就可以爬取复杂的网站 如果
  • vue中使用video插件vue-video-player

    进入我们的项目文件夹中 并打开命令行窗口 然后进行下面的步骤 1 安装vue video player 输入命令 npm install vue video player S 2 引入插件 在项目的入口文件main js中引入插件 如下 i
  • synopsys-SDC第六章——生成时钟

    synopsys SDC第六章 生成时钟 时钟派生方式 create generated clock edge divide multiply edge shift 多同源时钟 使能组合路径 其他注意事项 之前准备了一段时间的秋招 好久没有
  • java接入apiv3微信小程序支付(以java的eladmin框架为例)

    一 需要准备的资料 1 小程序AppID 如 wx2e56f5 2 商户号 如 1641 3 商户API私钥路径 什么是商户API证书 如何获取商户API证书 获取文件如下图 如 本地路径 E Env eladmin cert c2 api