【微信公众号】微信 jsapi 支付大概流程

这篇具有很好参考价值的文章主要介绍了【微信公众号】微信 jsapi 支付大概流程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、个人对微信 jsapi 支付的介绍

  • jsapi 支付可运用于微信小程序和 h5
  • jsapi 支付不会弹出二维码(这点与 native 支付不同)
  • jsapi 支付运用于移动端
  • native 支付运用于 PC 端

🔥 微信支付需要商家申请商户号,商务号需要和小程序或公众号(服务号)进行绑定
💦 在微信商务平台可开通 native 支付、jsapi 支付或其他支付方式
🔥 在微信商务平台能够获取到:mch_id(商户号)、
💦 在微信商务平台可配置 API v3 密钥(主要用于平台证书解密、回调信息解密)
🔥 下载并配置商户证书(获取证书序列号和商户私钥 ➡️ apiclient_key.pem)
💦 设置支付授权目录
🔥 设置授权域名

上述操作的详细步骤都可在下面的链接中找到:
https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_1.shtml

二、微信支付需要的数据库表(例子)

1. 订单表

订单表应与一个【用户表】关联,进而得知是那个用户创建的订单?进而得知某某用户创建的订单的支付情况。

CREATE TABLE `pay_order` (
  `id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '订单 id',
  `title` varchar(256) DEFAULT NULL COMMENT '订单标题',
  `order_no` varchar(50) DEFAULT NULL COMMENT '商户订单编号',
  `user_id` bigint(20) DEFAULT NULL COMMENT '用户 id', 
  `total_fee` int(11) DEFAULT NULL COMMENT '订单金额(分)', 
  `order_status` varchar(10) DEFAULT NULL COMMENT '订单状态',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

2. 支付信息表

该表中的字段大多来自微信商户平台返回的支付通知。该表记录的是微信商户平台对该笔账单的支付情况。

CREATE TABLE `payment_info` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '支付记录 id',
  `order_no` varchar(50) DEFAULT NULL COMMENT '商户订单编号',
  `transaction_id` varchar(50) DEFAULT NULL COMMENT '支付系统交易编号',
  `payment_type` varchar(20) DEFAULT NULL COMMENT '支付类型',
  `trade_type` varchar(20) DEFAULT NULL COMMENT '交易类型',
  `trade_state` varchar(50) DEFAULT NULL COMMENT '交易状态',
  `payer_total` int(11) DEFAULT NULL COMMENT '支付金额(分)',
  `content` text COMMENT '通知参数',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

3. 退款信息表

当用户支付的时候,需要创建一个【退款订单】,用于记录退款情况。

CREATE TABLE `refund_info` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '退款单 id',
  `order_no` varchar(50) DEFAULT NULL COMMENT '商户订单编号',
  `refund_no` varchar(50) DEFAULT NULL COMMENT '商户退款单编号',
  `refund_id` varchar(50) DEFAULT NULL COMMENT '支付系统退款单号',
  `total_fee` int(11) DEFAULT NULL COMMENT '原订单金额(分)',
  `refund` int(11) DEFAULT NULL COMMENT '退款金额(分)',
  `reason` varchar(50) DEFAULT NULL COMMENT '退款原因',
  `refund_status` varchar(10) DEFAULT NULL COMMENT '退款状态',
  `content_return` text COMMENT '申请退款返回参数',
  `content_notify` text COMMENT '退款结果通知参数',
  `create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', 
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;

三、微信支付必须的参数(配置文件)

wechat:
  mch-id: 1736608159
  mch-serial-no: 99A92506FC7B6BE2DA2F3F87898FFFF1C1D3811A
  private-key-path: apiclient_key.pem
  api-v3-key: 312f0ebadc062813ebc6812325fc2f23
  appid: wx60aa253aa13aaeb6
  domain: https://api.mch.weixin.qq.com
  notify-domain: https://helloboy.roroam.com
  app-secret: a712223142566a78a7beced6eff3ge59

✏️ 【mch-id】: 商户号(商家申请商户号后,可让管理员登录微信商户平台查看)

✏️ 【mch-serial-no】: 证书序列号(某些情况下,将需要更新密钥对和证书。为了保证更换过程中不影响 API 的使用,请求和应答的 HTTP 头部中包括证书序列号 ,以声明签名或者加密所用的密钥对和证书。)

✏️ 【private-key-path】: 商户 API 私钥文件路径(商户申请商户 API 证书时,会生成商户私钥,并保存在本地证书文件夹的文件 apiclient_key.pem 中。)
私钥和证书:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml

✏️ 【api-v3-key】: APIV3 秘钥(主要用于平台证书解密、回调信息解密)具体使用:证书和回调报文解密https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay4_2.shtml

✏️ 【appid】: 小程序或服务号的唯一标识(调用 jsapi 的下单接口时需要、前端 JS 方法调起支付的时候需要)

✏️ 【domain】: domain 是域名的意思(在此表示向微信商户平台发起请求的路径的基本路径

jsapi 下单接口:https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi
查询订单接口: https://api.mch.weixin.qq.com/v3/pay/transactions/id/{transaction_id}
关闭订单接口:https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}/close
申请退款接口:https://api.mch.weixin.qq.com/v3/refund/domestic/refunds
…(很多微信商务平台的接口的基本地址都是一样的,将它抽取为 domain)

✏️ 【notify_domain】: 通知域名(用户下单之后、退款之后,微信商户平台会向我们的商户系统返回通知 ➖ 告诉我们用户的支付情况或退款单的退款情况)【这个通知域名必须是外网能够访问得到的,可以是 ngrok 地址】

✏️ 【app_secret】: app 密码(在小程序或公众号中能够找到,可通过它向微信系统获取用户的 openid)【openid 用户的唯一标识】

四、WxPayConfig.java

第三节的配置文件中的内容大多都是为 WxPayConfig 而服务,下面把 WxPayConfig.java 中的代码拷贝如下,并做简单介绍(深层次的东西我不懂
在使用 Java 代码前,先引入一些 MAVEN 依赖,免得报错

1. MAVEN 依赖

🎈 微信支付 apiv3 开发工具包

  <!-- 微信支付 SDK(software development kit) -->
  <dependency>
      <groupId>com.github.wechatpay-apiv3</groupId>
      <artifactId>wechatpay-apache-httpclient</artifactId>
      <version>0.3.0</version>
  </dependency>

🎈 谷歌的 JSON 处理工具(可进行 JSON 字符串和 Java 对象的转换)

  <!--google 的 JSON 处理依赖-->
  <dependency>
      <groupId>com.google.code.gson</groupId>
      <artifactId>gson</artifactId>
  </dependency>

🎈 简单易用的缓存框架

  <!-- EhCache 缓存框架 -->
  <dependency>
      <groupId>org.ehcache</groupId>
      <artifactId>ehcache</artifactId>
  </dependency>

2. Java 代码(商户私钥、签名验证…)

@Slf4j
@Component
@Data
@ConfigurationProperties("wechat")
public class WxPayConfig implements ApplicationContextAware {
   private static WxPayConfig wxPayConfig;

   // 商户号
   private String mchId;

   // 商户API证书序列号
   private String mchSerialNo;

   // 商户私钥文件
   private String privateKeyPath;

   // APIv3密钥
   private String apiV3Key;

   // 应用的唯一标识
   private String appid;

   // 微信服务器地址
   private String domain;

   // 接收结果通知地址
   private String notifyDomain;

   private String appSecret;

   public static WxPayConfig getInstance() {
       return wxPayConfig;
   }

   @Override
   public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
       wxPayConfig = this;
   }

   /**
    * 获取商户私钥
    *
    * @param privateKeyPath 私钥文件所在路径
    * @return 私钥
    */
   public PrivateKey getPrivateKey(String privateKeyPath) {
       try {
           return PemUtil.loadPrivateKey(
                   new FileInputStream(privateKeyPath));
       } catch (Exception e) {
           e.printStackTrace();
           throw new IllegalArgumentException("私钥文件不存在(可能是私钥文件路径错误)");
       }
   }

   /**
    * 获取签名验证器
    * 签名验证器: 用于验签的对象
    */
   @Bean
   public ScheduledUpdateCertificatesVerifier getVerifier() {
       // 获取商户私钥
       PrivateKey privateKey = getPrivateKey(privateKeyPath);

       // 私钥签名对象
       PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);

       //身份认证对象
       WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);

       // 使用定时更新的签名验证器,不需要传入证书
       ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
               wechatPay2Credentials,
               apiV3Key.getBytes(StandardCharsets.UTF_8));

       return verifier;
   }

   /**
    * 获取微信远程 http 请求对象
    *
    * @param verifier 签名验证器
    */
   @Bean(name = "wxPayClient")
   public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) {
       WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
               .withMerchant(mchId, mchSerialNo, getPrivateKey(privateKeyPath))
               .withValidator(new WechatPay2Validator(verifier));
       return builder.build();
   }

   /**
    * 【签名】使用字段 appId、timeStamp、nonceStr、package 计算得出的签名值
    * appId: 应用的唯一标识
    * timeStamp: 时间戳
    * nonceStr: 随机字符串
    * package: 订单详情扩展字符串 (形如:"prepay_id=wx32j43k1kj5li1o")
    * <p>
    * 官方文档链接:https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_4.shtml#menu1
    *
    * @return 签名值
    */
   public static String createSignVal(String prepayId, String timeStampStr, String nonceStr) {
       // 构建签名串
       String signString = buildSignString(prepayId, timeStampStr, nonceStr);

       // 计算签名值
       String signVal = calculateSignVal(signString);
       return signVal;
   }

   /**
    * 计算签名值【下面是官方说明】
    * 绝大多数编程语言提供的签名函数支持对签名数据进行签名
    * <p>
    * 强烈建议商户调用该类函数, 使用【商户私钥】对【待签名串】进行【SHA256 with RSA】签名
    * 并对签名结果进行 Base64 编码得到签名值
    *
    * @param signStr 待签名字符串
    * @return 签名值
    */
   private static String calculateSignVal(String signStr) {
       try {
           // Signature: java 提供的用来为应用程序提供数字签名算法功能的类(数字签名用于确保数字数据的验证和完整性)
           // Signature: java.security
           Signature signature = Signature.getInstance("SHA256withRSA");
           // 初始化签名(官方要求使用商户私钥对待签名串进行 SHA256 with RSA 签名
           PrivateKey privateKey = WxPayConfig.getInstance().getPrivateKey(WxPayConfig.getInstance().getPrivateKeyPath());

           signature.initSign(privateKey);
           // 将数据添加到签名
           signature.update(signStr.getBytes(StandardCharsets.UTF_8));
           // 计算签名
           byte[] signRes = signature.sign();
           // 对签名结果(signRes)进行 Base64 编码
           // Base64 是 java.util 里面的类
           return Base64.getEncoder().encodeToString(signRes);
       } catch (Exception e) {
           e.printStackTrace();
           log.error("计算签名值出错:WxUtil - calculateSignVal");
           return null;
       }
   }

   /**
    * 【该方法服务于 createSignVal 方法】
    * 构造签名串【下面是官方说明】
    * 创建签名串:签名串一共有四行, 每一行为一个参数。行尾以【\n (换行符, ASCII 编码值为 0x0A) 结束】, 包括最后一行
    * 如果参数本身以【\n】结尾, 也需要附加一个【\n】
    * <p>
    * 签名格式内容:appid、timeStamp、nonceStr、package
    *
    * @param prepayId 预支付 id (调用 JSAPI 下单后可获得它的值)
    * @return 签名字符串
    */
   private static String buildSignString(String prepayId, String timeStampStr, String nonceStr) {
       return WxPayConfig.getInstance().getAppid() + "\n"
               + timeStampStr + "\n"
               + nonceStr + "\n"
               + "prepay_id=" + prepayId + "\n"; // 一定要拼接一个【prepay_id】字符串, 之前一直无法支付成功就是这里有问题
   }

}

上面代码中核心且复杂的方法有三个:

(1)getPrivateKey

📗 getPrivateKey:获取商户私钥(个人理解:对数据进行解密操作,公钥加密,私钥解密)【我不是很懂,大概知道一点点】

privateKeyPath 是商户私钥文件所在路径(一般都是放在类路径),使用 PemUtil 工具(来自 com.wechat.pay.contrib.apache.httpclient.util 包)加载 privateKeyPath 路径的商户私钥文件,并返回 PrivateKey 对象

    /**
     * 获取商户私钥
     *
     * @param privateKeyPath 私钥文件所在路径
     * @return 私钥
     */
    public PrivateKey getPrivateKey(String privateKeyPath) {
        try {
            return PemUtil.loadPrivateKey(
                    new FileInputStream(privateKeyPath));
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("私钥文件不存在(可能是私钥文件路径错误)");
        }
    }

(2)getVerifier

📗 getVerifier:获取签名验证器(个人理解:就是一个被人封装好的,用于验证签名的对象)。该方法中会使用到很多熟悉的东西,如:privateKeyPath(商户私钥文件路径)、mchSerialNo(证书序列号)、privateKey(私钥对象)、mchId(商户号)。签名验证器(Verifier)是一个帮助开发者对网络请求进行签名验证的东西,是被人封装好的,开发者直接使用它进行验签即可。

验证签名的作用:① 增加完整性校验(保证数据的来源和完整性);② 增加保密性

   /**
    * 获取签名验证器
    * 签名验证器: 用于验签的对象
    */
   @Bean
   public ScheduledUpdateCertificatesVerifier getVerifier() {
       // 获取商户私钥
       PrivateKey privateKey = getPrivateKey(privateKeyPath);

       // 私钥签名对象
       PrivateKeySigner privateKeySigner = new PrivateKeySigner(mchSerialNo, privateKey);

       // 身份认证对象
       WechatPay2Credentials wechatPay2Credentials = new WechatPay2Credentials(mchId, privateKeySigner);

       // 使用定时更新的签名验证器,不需要传入证书
       ScheduledUpdateCertificatesVerifier verifier = new ScheduledUpdateCertificatesVerifier(
               wechatPay2Credentials,
               apiV3Key.getBytes(StandardCharsets.UTF_8));

       return verifier;
   }

(3)getWxPayClient

📗 getWxPayClient:CloseableHttpClient 对象是微信支付平台推荐的实现远程 HTTP 请求的对象。SpringBoot 项目启动后,会创建 CloseableHttpClient 对象的实例(把它的实例放入 IoC 容器)。后期我们需要向微信商务平台发送网络请求(如:下单、退款、关单…)的时候就使用 IoC 容器里面的 CloseableHttpClient 对象。

创建它的实例需要签名验证器作为参数。代码内部也要使用到商户号、证书序列号和商户秘钥。

官方地址:https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay
/wechatpay6_0.shtml
【微信公众号】微信 jsapi 支付大概流程

   /**
    * 获取微信远程 http 请求对象
    *
    * @param verifier 签名验证器
    */
   @Bean(name = "wxPayClient")
   public CloseableHttpClient getWxPayClient(ScheduledUpdateCertificatesVerifier verifier) {
       WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
               .withMerchant(mchId, mchSerialNo, getPrivateKey(privateKeyPath))
               .withValidator(new WechatPay2Validator(verifier));
       return builder.build();
   }

五、工具类相关

1. WxPayUtil

该类中有五个方法,我简单说明一下,后期都会使用到。
⛄️ ① notifyCiphertext2plainText:把通知密文转换为明文。(用户支付之后成功和商户系统退款成功之后)文章来源地址https://www.toymoban.com/news/detail-494563.html

/**
 * 用于创建订单(支付订单、退款订单)编号
 */
public class WxPayUtil {
    /**
     * 通知密文(ciphertext)转明文
     *
     * @param notifyMap 包含进行解密所需的参数
     * @return 明文
     */
    public static String notifyCiphertext2plainText(Map notifyMap) {
        try {
            // resource: 通知数据
            Map notifyData = (Map) notifyMap.get("resource");
            // 数据密文
            String ciphertext = (String) notifyData.get("ciphertext");
            // 附加数据
            String associatedData = (String) notifyData.get("associated_data");
            // 随机串
            String nonce = (String) notifyData.get("nonce");

            // 创建解密对象
            AesUtil aesUtil = new AesUtil(WxPayConfig.getInstance().getApiV3Key().getBytes());

            return aesUtil.decryptToString(associatedData.getBytes(),
                    nonce.getBytes(StandardCharsets.UTF_8), ciphertext);
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalArgumentException("微信支付通知密文转密文出现错误");
        }
    }

    /**
     * 生成支付订单编号
     */
    public static String generatePayOrderNumber() {
        return "ORDER_" + generateNumber();
    }

    /**
     * 生成退款订单编号
     */
    public static String generateRefundNumber() {
        return "REFUND_" + generateNumber();
    }

    /**
     * 生成订单编号
     */
    private static String generateNumber() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
        String newDate = sdf.format(new Date());
        StringBuilder result = new StringBuilder();
        Random random = new Random();
        for (int i = 0; i < 3; i++) {
            result.append(random.nextInt(10));
        }
        return newDate + result + UUID.randomUUID().toString().substring(0, 5);
    }

    /**
     * 获取当前时间字符串
     *
     * @return 当前时间字符串
     */
    public static String getCurTimeStr() {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return sdf.format(new Date()).toString();
    }

}

到了这里,关于【微信公众号】微信 jsapi 支付大概流程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 微信的 h5 支付和 jsapi 支付

    申请地址: https://pay.weixin.qq.com/ 如果你还没有微信商户号,请点击上面的链接进行申请,如果已经有了,可以跳过这一步 首先点击 账户中心 ▶ API安全 ▶ 申请API证书 申请详细步骤: https://kf.qq.com/faq/161222NneAJf161222U7fARv.html 首先点击 账户中心 ▶ API安全 ▶ 设置APIv3密钥 ▶

    2024年02月13日
    浏览(46)
  • 〔支付接入〕微信的 h5 支付和 jsapi 支付

    申请地址: https://pay.weixin.qq.com/ 如果你还没有微信商户号,请点击上面的链接进行申请,如果已经有了,可以跳过这一步 首先点击 账户中心 ▶ API安全 ▶ 申请API证书 申请详细步骤: https://kf.qq.com/faq/161222NneAJf161222U7fARv.html 首先点击 账户中心 ▶ API安全 ▶ 设置APIv3密钥 ▶

    2024年02月13日
    浏览(52)
  • java对接微信支付:JSAPI支付成功之“微信回调”

    承接上一篇微信支付,现在简单说一下 微信支付回调 目录 一、支付回调 二、微信回调地址问题 1.本地/上线测试 2.控制器调用接口(代码) 总结 当用户支付成功之后,支付平台会向我们指定的服务器接口发送请求传递订单支付状态数据 如果你是再本地进行测试,那就需要使用

    2024年02月12日
    浏览(41)
  • uniapp微信小程序JSAPI支付前端生成签名,并调起微信支付

    签名方式使用的是SHA256withRSA 插件 npm install jsrsasign 使用

    2024年01月17日
    浏览(71)
  • SpringBoot 整合微信小程序微信支付V3 jsapi (支付、退款)

    最近的一个微信小程序项目里有用到微信支付,网上找的资料都是特别乱,看起来特别懵,结合了好多文章的内容,终于做了出来,可能我的这个博文看起来也是特别乱,但是是可以直接C走简单改一改就可以用的。(支付成功回调,和退款回调因为昨天刚在阿里申请的域名还

    2024年04月25日
    浏览(50)
  • 微信支付(JSAPI支付)/支付宝支付(手机网站支付)实现思路及实现方案-无源码

    停车系统 一个二维码同时支持微信及支付宝扫码付款,使用手机网站实现 临时车费用缴费二维码需要通知支持微信及支付宝。 用户缴纳的停车费直接到各个商户的账户上,不经过停车系统开发公司。 微信:使用微信服务商提供的服务 支付宝:使用支付服务商提供的服务 两

    2024年02月09日
    浏览(40)
  • 【微信支付】springboot-java接入微信支付-JSAPI支付/查单/退款/发送红包(三)---退款

    微信支付开发文档:https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/create.html 退款与查单的请求头类似,但是查单是GET请求,所以在构造签名的时候相对简单些,但是退款请求中有请求参数,在构造签名时,需要将请求体添加到请求头参数中。 1、构造请求参数 查看微信支付开

    2024年01月19日
    浏览(57)
  • 【微信支付】springboot-java接入微信支付-JSAPI支付/查单/退款/发送红包(二)---查单

    文章地址:https://blog.csdn.net/ssdadasd15623/article/details/134684556 查询订单分为微信订单号查询以及商户订单号查询,这里使用商户订单号,也就是自己的系统的订单号 https://pay.weixin.qq.com/docs/merchant/apis/jsapi-payment/query-by-out-trade-no.html 在请求接口时,注意⚠️:请求参数内的Authori

    2024年02月03日
    浏览(47)
  • 微信支付,JSAPI支付,APP支付,H5支付,Native支付,小程序支付功能详情以及回调处理

    支付wiki: https://pay.weixin.qq.com/wiki/doc/apiv3/index.shtml 支付api: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/index.shtml 开发工具包(SDK)下载: https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay6_0.shtml#part-1 1.1简介 JSAPI支付是指商户通过调用微信支付提供的JSAPI接口,在支付场景中调起微信支付模

    2023年04月18日
    浏览(49)
  • 微信小程序JSAPI下单支付PHP前后端教程

    准备数据: 微信支付API证书,微信支付商户号,小程序appid,微信支付API证书序列号 获取微信支付api证书教程:如何下载微信支付证书(API证书)_荒~的博客-CSDN博客_微信支付证书 获取微信支付API证书序列号:点击管理证书即可看到   第一步:生成预支付交易单 参考文档:

    2024年02月11日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包