Bläddra i källkod

微信支付接入

skyline 2 år sedan
förälder
incheckning
18b1d6d5d9
39 ändrade filer med 749 tillägg och 308 borttagningar
  1. 22 0
      admin/src/main/java/com/kym/admin/utils/AdminAccountGenerator.java
  2. 1 1
      admin/src/main/java/com/kym/admin/utils/MybatisPlusGeneratorForAdmin.java
  3. 1 2
      common/pom.xml
  4. 0 31
      common/src/main/java/com/kym/common/config/WechatPaymentConfig.java
  5. 3 3
      common/src/main/java/com/kym/common/config/WxConfig.java
  6. 24 0
      common/src/main/java/com/kym/common/config/WxPayConfig.java
  7. 81 0
      common/src/main/java/com/kym/common/utils/OrderUtils.java
  8. 67 0
      common/src/main/java/com/kym/common/utils/RequestBodyUtil.java
  9. 11 0
      common/src/main/java/com/kym/common/wxpay/WxJsApi.java
  10. 1 1
      entity/src/main/java/com/kym/entity/admin/EquipmentInfo.java
  11. 5 5
      entity/src/main/java/com/kym/entity/miniapp/Account.java
  12. 5 5
      entity/src/main/java/com/kym/entity/miniapp/ChargeOrder.java
  13. 99 0
      entity/src/main/java/com/kym/entity/miniapp/PayLog.java
  14. 6 6
      entity/src/main/java/com/kym/entity/miniapp/WalletDetail.java
  15. 0 89
      mapper/src/main/java/com/kym/mapper/MybatisPlusGenerator.java
  16. 16 0
      mapper/src/main/java/com/kym/mapper/miniapp/PayLogMapper.java
  17. 8 6
      mapper/src/main/resources/mappers/miniapp/ChargeOrderMapper.xml
  18. 31 0
      mapper/src/main/resources/mappers/miniapp/PayLogMapper.xml
  19. 2 2
      mapper/src/main/resources/mappers/miniapp/WalletDetailMapper.xml
  20. 0 5
      miniapp/pom.xml
  21. 0 13
      miniapp/src/main/java/com/kym/miniapp/controller/ChargerController.java
  22. 18 0
      miniapp/src/main/java/com/kym/miniapp/controller/PayLogController.java
  23. 18 1
      miniapp/src/main/java/com/kym/miniapp/controller/PaymentController.java
  24. 4 3
      miniapp/src/main/java/com/kym/miniapp/utils/MybatisPlusGeneratorForMiniApp.java
  25. 9 6
      miniapp/src/main/resources/application.yml
  26. 0 21
      miniapp/src/main/resources/mappers/AccountMapper.xml
  27. 0 33
      miniapp/src/main/resources/mappers/ChargeOrderMapper.xml
  28. 0 27
      miniapp/src/main/resources/mappers/WalletDetailMapper.xml
  29. 7 0
      service/pom.xml
  30. 34 31
      service/src/main/java/com/kym/service/enplus/impl/EnNotifyServiceImpl.java
  31. 16 0
      service/src/main/java/com/kym/service/miniapp/PayLogService.java
  32. 2 0
      service/src/main/java/com/kym/service/miniapp/WalletDetailService.java
  33. 1 0
      service/src/main/java/com/kym/service/miniapp/impl/ChargeOrderServiceImpl.java
  34. 9 11
      service/src/main/java/com/kym/service/miniapp/impl/ChargeServiceImpl.java
  35. 20 0
      service/src/main/java/com/kym/service/miniapp/impl/PayLogServiceImpl.java
  36. 5 5
      service/src/main/java/com/kym/service/miniapp/impl/UserServiceImpl.java
  37. 6 1
      service/src/main/java/com/kym/service/miniapp/impl/WalletDetailServiceImpl.java
  38. 14 0
      service/src/main/java/com/kym/service/wechat/WxPayService.java
  39. 203 0
      service/src/main/java/com/kym/service/wechat/impl/WxPayServiceImpl.java

+ 22 - 0
admin/src/main/java/com/kym/admin/utils/AdminAccountGenerator.java

@@ -0,0 +1,22 @@
+package com.kym.admin.utils;
+
+import cn.hutool.crypto.digest.DigestAlgorithm;
+import cn.hutool.crypto.digest.Digester;
+
+/**
+ * @author skyline
+ * @description 加盟商密码生成
+ * @date 2023-08-11 16:01
+ */
+public class AdminAccountGenerator {
+    public static void main(String[] args) {
+        // 密码生成 先把账号md5,然后取前5位,然后把密码和这个5位字符拼接在一起,再md5
+        var username = "18569535949";
+        var password = "abc123";
+
+        Digester md5 = new Digester(DigestAlgorithm.MD5);
+        var str1 = md5.digestHex(username).substring(0,5);
+        var str2 = md5.digestHex(password.concat(str1));
+        System.out.println(str2);
+    }
+}

+ 1 - 1
admin/src/main/java/com/kym/admin/utils/MybatisPlusGeneratorForAdmin.java

@@ -39,7 +39,7 @@ public class MybatisPlusGeneratorForAdmin {
                                     OutputFile.serviceImpl, "D://快与慢充电桩/code/charge-java/service/src/main/java/com/kym/service/admin/impl",
                                     OutputFile.mapper, "D://快与慢充电桩/code/charge-java/mapper/src/main/java/com/kym/mapper/admin",
                                     OutputFile.controller, "D://快与慢充电桩/code/charge-java/admin/src/main/java/com/kym/admin/controller",
-                                    OutputFile.xml, "D://快与慢充电桩/code/charge-java/admin/src/main/resources/mappers"
+                                    OutputFile.xml, "D://快与慢充电桩/code/charge-java/mapper/src/main/resources/mappers/admin"
 
                             ));
                 })

+ 1 - 2
common/pom.xml

@@ -76,7 +76,6 @@
             <version>1.35.0.RC</version>
         </dependency>
 
-
         <dependency>
             <groupId>com.squareup.okhttp3</groupId>
             <artifactId>okhttp</artifactId>
@@ -86,7 +85,7 @@
         <dependency>
             <groupId>cn.hutool</groupId>
             <artifactId>hutool-all</artifactId>
-            <version>5.8.16</version>
+            <version>5.8.21</version>
         </dependency>
 
         <dependency>

+ 0 - 31
common/src/main/java/com/kym/common/config/WechatPaymentConfig.java

@@ -1,31 +0,0 @@
-package com.kym.common.config;
-
-import org.springframework.context.annotation.Configuration;
-
-/**
- * @author skyline
- * @description
- * @date 2023-07-22 23:11
- */
-@Configuration
-public class WechatPaymentConfig {
-/*    @Autowired
-    private WechatPaymentProperties properties;
-
-    @Bean
-    public WxMaConfig wxMaConfig() {
-        WxMaInMemoryConfig config = new WxMaInMemoryConfig();
-        config.setAppid(properties.getAppId());
-        config.setSecret(properties.getAppSecret());
-        return config;
-    }
-
-
-    @Bean
-    public WxMaService wxMaService(WxMaConfig maConfig) {
-        WxMaService service = new WxMaServiceImpl();
-        service.setWxMaConfig(maConfig);
-        return service;
-    }*/
-
-}

+ 3 - 3
common/src/main/java/com/kym/common/config/WxMiniAppConfig.java → common/src/main/java/com/kym/common/config/WxConfig.java

@@ -6,15 +6,15 @@ import org.springframework.context.annotation.Configuration;
 
 /**
  * @author skyline
- * @description 微信支付小程序
+ * @description 微信账号配置
  * @date 2023-07-22 23:09
  */
 @Data
 @Configuration
 @ConfigurationProperties(prefix = "wechat.miniapp")
-public class WxMiniAppConfig {
+public class WxConfig {
 
-    private String appId;
+    private String appid;
 
     private String secret;
 

+ 24 - 0
common/src/main/java/com/kym/common/config/WxPayConfig.java

@@ -0,0 +1,24 @@
+package com.kym.common.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author skyline
+ * @description 微信支付配置
+ * @date 2023-07-22 23:09
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "wechat.payment")
+public class WxPayConfig {
+    private String appid;
+    private String mchid;
+    private String mchsn;
+    private String notifyUrl;
+    private String v3key;
+    private String certPath;
+    private String keyPath;
+
+}

+ 81 - 0
common/src/main/java/com/kym/common/utils/OrderUtils.java

@@ -0,0 +1,81 @@
+package com.kym.common.utils;
+
+import cn.hutool.core.util.RandomUtil;
+
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @author skyline
+ * @description 订单号生成
+ * @date 2023-08-12 17:26
+ */
+public class OrderUtils {
+
+    // 生成24位唯一订单号码,格式:YYYY-MMDD-HHII-SS-NNNN,NNNN-CC,
+    // 其中:YYYY=年份,MM=月份,DD=日期,HH=24格式小时,II=分,SS=秒,NNNNNNNN=随机数,CC=检查码
+    public static String getOrderNo() {
+        var orderNoMain = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")).concat(String.valueOf(RandomUtil.randomInt(10000000, 99999999)));
+        var orderNoSum = 0;
+        for (int i = 0; i < orderNoMain.length(); i++) {
+            orderNoSum += Integer.parseInt(orderNoMain.substring(0, 1));
+        }
+        var j = (100 - orderNoSum % 100) % 100;
+        return orderNoMain.concat(str_pad(String.valueOf((100 - orderNoSum % 100) % 100), 2, "0", "STR_PAD_LEFT"));
+    }
+
+
+    public static String str_pad(String input, int length, String pad, String sense) {
+        int resto_pad = length - input.length();
+        String padded = "";
+
+        if (resto_pad <= 0) {
+            return input;
+        }
+
+        if (sense.equals("STR_PAD_RIGHT")) {
+            padded = input;
+            padded += _fill_string(pad, resto_pad);
+        } else if (sense.equals("STR_PAD_LEFT")) {
+            padded = _fill_string(pad, resto_pad);
+            padded += input;
+        } else // STR_PAD_BOTH
+        {
+            int pad_left = (int) Math.ceil(resto_pad / 2);
+            int pad_right = resto_pad - pad_left;
+
+            padded = _fill_string(pad, pad_left);
+            padded += input;
+            padded += _fill_string(pad, pad_right);
+        }
+        return padded;
+    }
+
+
+    protected static String _fill_string(String pad, int resto) {
+        boolean first = true;
+        String padded = "";
+
+        if (resto >= pad.length()) {
+            for (int i = resto; i >= 0; i = i - pad.length()) {
+                if (i >= pad.length()) {
+                    if (first) {
+                        padded = pad;
+                    } else {
+                        padded += pad;
+                    }
+                } else {
+                    if (first) {
+                        padded = pad.substring(0, i);
+                    } else {
+                        padded += pad.substring(0, i);
+                    }
+                }
+                first = false;
+            }
+        } else {
+            padded = pad.substring(0, resto);
+        }
+        return padded;
+    }
+}

+ 67 - 0
common/src/main/java/com/kym/common/utils/RequestBodyUtil.java

@@ -0,0 +1,67 @@
+package com.kym.common.utils;
+
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+
+/**
+ * @author 这段代码来自dubbo
+ * @description
+ * @date 2023-08-12 10:15
+ */
+public class RequestBodyUtil {
+
+    private static final int BUFFER_SIZE = 1024 * 8;
+
+    /**
+     * read string.
+     *
+     * @param reader Reader instance.
+     * @return String.
+     * @throws IOException
+     */
+    public static String read(Reader reader) throws IOException {
+        StringWriter writer = new StringWriter();
+        try {
+            write(reader, writer);
+            return writer.getBuffer().toString();
+        } finally {
+            writer.close();
+        }
+    }
+
+    /**
+     * write.
+     *
+     * @param reader Reader.
+     * @param writer Writer.
+     * @return count.
+     * @throws IOException
+     */
+    public static long write(Reader reader, Writer writer) throws IOException {
+        return write(reader, writer, BUFFER_SIZE);
+    }
+
+    /**
+     * write.
+     *
+     * @param reader     Reader.
+     * @param writer     Writer.
+     * @param bufferSize buffer size.
+     * @return count.
+     * @throws IOException
+     */
+    public static long write(Reader reader, Writer writer, int bufferSize) throws IOException {
+        int read;
+        long total = 0;
+        char[] buf = new char[BUFFER_SIZE];
+        while ((read = reader.read(buf)) != -1) {
+            writer.write(buf, 0, read);
+            total += read;
+        }
+        return total;
+    }
+
+}

+ 11 - 0
common/src/main/java/com/kym/common/wxpay/WxJsApi.java

@@ -0,0 +1,11 @@
+package com.kym.common.wxpay;
+
+/**
+ * @author skyline
+ * @description JSAPI下单
+ * @date 2023-08-10 14:01
+ */
+public class WxJsApi {
+
+
+}

+ 1 - 1
entity/src/main/java/com/kym/entity/admin/EquipmentInfo.java

@@ -72,7 +72,7 @@ public class EquipmentInfo implements Serializable {
     /**
      * 额定功率 千瓦
      */
-    private BigDecimal power;
+    private Double power;
 
     /**
      * 网络状态:0-离线 1-在线

+ 5 - 5
entity/src/main/java/com/kym/entity/miniapp/Account.java

@@ -1,12 +1,12 @@
 package com.kym.entity.miniapp;
 
 import com.baomidou.mybatisplus.annotation.TableName;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
 /**
  * <p>
  * 用户账户表
@@ -32,12 +32,12 @@ public class Account implements Serializable {
     /**
      * 余额
      */
-    private BigDecimal balance;
+    private Integer balance;
 
     /**
      * 冻结金额
      */
-    private BigDecimal frozenAmount;
+    private Integer frozenAmount;
 
     /**
      * 状态: 0禁用 1启用

+ 5 - 5
entity/src/main/java/com/kym/entity/miniapp/ChargeOrder.java

@@ -51,27 +51,27 @@ public class ChargeOrder implements Serializable {
     /**
      * 电池剩余电量
      */
-    private BigDecimal soc;
+    private Double soc;
 
     /**
      * 累积充电量(度)
      */
-    private BigDecimal totalPower;
+    private Double totalPower;
 
     /**
      * 累积总金额(元)
      */
-    private BigDecimal totalMoney;
+    private Integer totalMoney;
 
     /**
      * 累积电费(元)
      */
-    private BigDecimal elecMoney;
+    private Integer elecMoney;
 
     /**
      * 累积服务费(元)
      */
-    private BigDecimal serviceMoney;
+    private Integer serviceMoney;
 
     /**
      * 时段数:0~32

+ 99 - 0
entity/src/main/java/com/kym/entity/miniapp/PayLog.java

@@ -0,0 +1,99 @@
+package com.kym.entity.miniapp;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 支付日志
+ * </p>
+ *
+ * @author skyline
+ * @since 2023-08-12
+ */
+@Getter
+@Setter
+@TableName("t_pay_log")
+public class PayLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private Long id;
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 微信用户唯一标识
+     */
+    private String openid;
+
+    /**
+     * 银行类型,采用字符串类型的银行标识
+     */
+    private String bankType;
+
+    /**
+     * 商户号
+     */
+    private String mchId;
+
+    /**
+     * 商户系统内部订单号,只能是数字、大小写字母_-*且在同一个商户号下唯一
+     */
+    private String outTradeNo;
+
+    /**
+     * 微信支付系统生成的订单号。
+     */
+    private String transactionId;
+
+    /**
+     * 支付完成时间 示例值:2018-06-08T10:34:56+08:00
+     */
+    private String successTime;
+
+    /**
+     * 交易类型,枚举值:JSAPI:公众号支付 NATIVE:扫码支付 APP:APP支付 MICROPAY:付款码支付 MWEB:H5支付 FACEPAY:刷脸支付
+     */
+    private String tradeType;
+
+    /**
+     * 交易状态,枚举值:SUCCESS:支付成功REFUND:转入退款NOTPAY:未支付CLOSED:已关闭REVOKED:已撤销(付款码支付)USERPAYING:用户支付中(付款码支付)PAYERROR:支付失败(其他原因,如银行返回失败)
+     */
+    private String tradeState;
+
+    /**
+     * 附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用,实际情况下只有支付完成状态才会返回该字段。
+     */
+    private String attach;
+
+    /**
+     * 订单总金额,单位为分。
+     */
+    private Integer total;
+
+    /**
+     * 用户支付币种
+     */
+    private String currency;
+
+    /**
+     * 用户支付金额,单位为分。
+     */
+    private Integer payerTotal;
+
+    /**
+     * 用户支付币种
+     */
+    private String payerCurrency;
+
+    private LocalDateTime createTime;
+
+    private LocalDateTime updateTime;
+}

+ 6 - 6
entity/src/main/java/com/kym/entity/miniapp/WalletDetail.java

@@ -1,12 +1,12 @@
 package com.kym.entity.miniapp;
 
 import com.baomidou.mybatisplus.annotation.TableName;
-import java.io.Serializable;
-import java.math.BigDecimal;
-import java.time.LocalDateTime;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
 /**
  * <p>
  * 用户账户表
@@ -37,7 +37,7 @@ public class WalletDetail implements Serializable {
     /**
      * 币种
      */
-    private String current;
+    private String currency;
 
     /**
      * 订单号
@@ -47,12 +47,12 @@ public class WalletDetail implements Serializable {
     /**
      * 金额
      */
-    private BigDecimal amount;
+    private Integer amount;
 
     /**
      * 手续费
      */
-    private BigDecimal commission;
+    private Integer commission;
 
     /**
      * 交易id type为1是pay_log的id,type为3是charge_order的id

+ 0 - 89
mapper/src/main/java/com/kym/mapper/MybatisPlusGenerator.java

@@ -1,89 +0,0 @@
-package com.kym.mapper;
-
-import com.baomidou.mybatisplus.generator.FastAutoGenerator;
-import com.baomidou.mybatisplus.generator.config.OutputFile;
-import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
-
-import java.util.Collections;
-
-/**
- * mybatis-plus-generator代码生成
- *
- * @author skyline
- */
-public class MybatisPlusGenerator {
-
-    public static void main(String[] args) {
-        // 指定数据源
-        FastAutoGenerator.create("jdbc:mysql://localhost:3306/charge_admin", "root", "root")
-                .globalConfig(builder -> {
-                    builder.author("skyline")
-                            // 指定输出目录
-                            .outputDir("D://快与慢充电桩/code/charge-java/src/main/java");
-                })
-                .packageConfig(builder -> {
-                    // 设置父包名
-                    builder.parent("com.kym")
-                            // 设置父包模块名
-                            .moduleName("charge")
-                            .entity("entity")
-                            .service("service")
-                            .serviceImpl("service.impl")
-                            .mapper("mapper")
-                            .xml("mapper.xml")
-                            .controller("controller")
-                            // 设置mapperXml生成路径
-                            .pathInfo(Collections.singletonMap(OutputFile.xml, "D://快与慢充电桩/code/charge-java/src/main/resources/mappers"));
-                })
-
-                .strategyConfig(builder -> {
-                    // 设置需要生成的表名
-                    builder.addInclude(
-//                                    "t_user",
-//                                    "t_account",
-//                                    "t_station",
-//                                    "t_charge_order",
-                                    "t_system_log"
-                            )
-                            // 设置过滤表前缀
-                            .addTablePrefix("t_");
-
-                    // entity配置
-                    builder.entityBuilder()
-                            .enableFileOverride()
-                            .enableLombok();
-
-                    // controller配置
-                    builder.controllerBuilder()
-                            .enableFileOverride()
-                            .enableRestStyle()
-                            .enableHyphenStyle()
-//                            .superClass(BaseController.class)
-                            .formatFileName("%sController");
-
-                    // service配置
-                    builder.serviceBuilder()
-                            .enableFileOverride()
-                            .formatServiceFileName("%sService")
-                            .formatServiceImplFileName("%sServiceImpl");
-
-                    // mapper配置
-                    builder.mapperBuilder()
-                            .enableFileOverride()
-                            .enableBaseResultMap()
-                            .enableBaseColumnList()
-                            .formatMapperFileName("%sMapper")
-                            .formatXmlFileName("%sMapper")
-                            .build();
-
-
-                    builder.build();
-
-                })
-
-                // 使用Freemarker引擎模板,默认的是Velocity引擎模板
-                .templateEngine(new FreemarkerTemplateEngine())
-                .execute();
-    }
-
-}

+ 16 - 0
mapper/src/main/java/com/kym/mapper/miniapp/PayLogMapper.java

@@ -0,0 +1,16 @@
+package com.kym.mapper.miniapp;
+
+import com.kym.entity.miniapp.PayLog;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * <p>
+ * 支付日志 Mapper 接口
+ * </p>
+ *
+ * @author skyline
+ * @since 2023-08-12
+ */
+public interface PayLogMapper extends BaseMapper<PayLog> {
+
+}

+ 8 - 6
mapper/src/main/resources/mappers/miniapp/ChargeOrderMapper.xml

@@ -3,7 +3,7 @@
 <mapper namespace="com.kym.mapper.miniapp.ChargeOrderMapper">
 
     <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.kym.entity.admin.ChargeOrder">
+    <resultMap id="BaseResultMap" type="com.kym.entity.miniapp.ChargeOrder">
         <id column="id" property="id" />
         <result column="user_id" property="userId" />
         <result column="station_id" property="stationId" />
@@ -11,21 +11,23 @@
         <result column="connector_id" property="connectorId" />
         <result column="start_time" property="startTime" />
         <result column="end_time" property="endTime" />
+        <result column="soc" property="soc" />
         <result column="total_power" property="totalPower" />
-        <result column="total_cost" property="totalCost" />
-        <result column="elec_bill" property="elecBill" />
-        <result column="service_fee" property="serviceFee" />
-        <result column="stop_reason" property="stopReason" />
+        <result column="total_money" property="totalMoney" />
+        <result column="elec_money" property="elecMoney" />
+        <result column="service_money" property="serviceMoney" />
         <result column="sum_period" property="sumPeriod" />
         <result column="charge_detail" property="chargeDetail" />
+        <result column="order_status" property="orderStatus" />
         <result column="charge_status" property="chargeStatus" />
+        <result column="stop_reason" property="stopReason" />
         <result column="create_time" property="createTime" />
         <result column="update_time" property="updateTime" />
     </resultMap>
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, user_id, station_id, start_charge_seq, connector_id, start_time, end_time, total_power, total_cost, elec_bill, service_fee, stop_reason, sum_period, charge_detail, charge_status, create_time, update_time
+        id, user_id, station_id, start_charge_seq, connector_id, start_time, end_time, soc, total_power, total_money, elec_money, service_money, sum_period, charge_detail, order_status, charge_status, stop_reason, create_time, update_time
     </sql>
 
 </mapper>

+ 31 - 0
mapper/src/main/resources/mappers/miniapp/PayLogMapper.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kym.mapper.miniapp.PayLogMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.kym.entity.miniapp.PayLog">
+        <id column="id" property="id" />
+        <result column="user_id" property="userId" />
+        <result column="openid" property="openid" />
+        <result column="bank_type" property="bankType" />
+        <result column="mch_id" property="mchId" />
+        <result column="out_trade_no" property="outTradeNo" />
+        <result column="transaction_id" property="transactionId" />
+        <result column="success_time" property="successTime" />
+        <result column="trade_type" property="tradeType" />
+        <result column="trade_state" property="tradeState" />
+        <result column="attach" property="attach" />
+        <result column="total" property="total" />
+        <result column="currency" property="currency" />
+        <result column="payer_total" property="payerTotal" />
+        <result column="payer_currency" property="payerCurrency" />
+        <result column="create_time" property="createTime" />
+        <result column="update_time" property="updateTime" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        id, user_id, openid, bank_type, mch_id, out_trade_no, transaction_id, success_time, trade_type, trade_state, attach, total, currency, payer_total, payer_currency, create_time, update_time
+    </sql>
+
+</mapper>

+ 2 - 2
mapper/src/main/resources/mappers/miniapp/WalletDetailMapper.xml

@@ -8,7 +8,7 @@
         <result column="user_id" property="userId" />
         <result column="type" property="type" />
         <result column="current" property="current" />
-        <result column="order_id" property="orderId" />
+        <result column="order_no" property="orderNo" />
         <result column="amount" property="amount" />
         <result column="commission" property="commission" />
         <result column="transaction_id" property="transactionId" />
@@ -21,7 +21,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id, user_id, type, current, order_id, amount, commission, transaction_id, transaction_time, status, remark, create_time, update_time
+        id, user_id, type, current, order_no, amount, commission, transaction_id, transaction_time, status, remark, create_time, update_time
     </sql>
 
 </mapper>

+ 0 - 5
miniapp/pom.xml

@@ -18,11 +18,6 @@
     </properties>
 
     <dependencies>
-        <dependency>
-            <groupId>com.github.wechatpay-apiv3</groupId>
-            <artifactId>wechatpay-java</artifactId>
-            <version>0.2.10</version>
-        </dependency>
         <dependency>
             <groupId>com.kym</groupId>
             <artifactId>common</artifactId>

+ 0 - 13
miniapp/src/main/java/com/kym/miniapp/controller/ChargerController.java

@@ -156,17 +156,4 @@ public class ChargerController {
         return new EnResponse(enNotifyService.handleNotificationChargeOrderInfo(json));
     }
 
-
-    /**
-     * 推送充电订单信息
-     *
-     * @param json
-     * @return
-     */
-    @PostMapping("/check_charge_orders")
-    EnResponse checkChargeOrders(@RequestBody JSONObject json) {
-        return new EnResponse(enNotifyService.handleCheckChargeOrders(json));
-    }
-
-
 }

+ 18 - 0
miniapp/src/main/java/com/kym/miniapp/controller/PayLogController.java

@@ -0,0 +1,18 @@
+package com.kym.miniapp.controller;
+
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 支付日志 前端控制器
+ * </p>
+ *
+ * @author skyline
+ * @since 2023-08-12
+ */
+@RestController
+@RequestMapping("/pay-log")
+public class PayLogController {
+
+}

+ 18 - 1
miniapp/src/main/java/com/kym/miniapp/controller/PaymentController.java

@@ -1,15 +1,32 @@
 package com.kym.miniapp.controller;
 
+import com.kym.common.R;
+import com.kym.service.wechat.WxPayService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestController;
 
+import java.math.BigDecimal;
+
 /**
  * @author skyline
  * @description
  * @date 2023-07-22 20:36
  */
-@RestController("/api/pay")
+@RestController
+@RequestMapping("/api/pay")
 public class PaymentController {
 
+    @Autowired
+    private WxPayService wxPayService;
+
+    @GetMapping("/getId")
+    @ResponseBody
+    R getId() {
+        return R.success(wxPayService.prepay(BigDecimal.valueOf(0.01), "oK-oR5gAn9hrYNim4x64l4kzmMXs"));
+    }
 
 
 }

+ 4 - 3
miniapp/src/main/java/com/kym/miniapp/utils/MybatisPlusGeneratorForMiniApp.java

@@ -39,7 +39,7 @@ public class MybatisPlusGeneratorForMiniApp {
                                     OutputFile.serviceImpl, "D://快与慢充电桩/code/charge-java/service/src/main/java/com/kym/service/miniapp/impl",
                                     OutputFile.mapper, "D://快与慢充电桩/code/charge-java/mapper/src/main/java/com/kym/mapper/miniapp",
                                     OutputFile.controller, "D://快与慢充电桩/code/charge-java/miniapp/src/main/java/com/kym/miniapp/controller",
-                                    OutputFile.xml, "D://快与慢充电桩/code/charge-java/miniapp/src/main/resources/mappers"
+                                    OutputFile.xml, "D://快与慢充电桩/code/charge-java/mapper/src/main/resources/mappers/miniapp"
 
                             ));
                 })
@@ -50,9 +50,10 @@ public class MybatisPlusGeneratorForMiniApp {
 //                                    "t_user",
 //                                    "t_account"
 //                                    "t_charge_order",
-                                    "t_wallet_detail"
+//                                    "t_wallet_detail",
 //                                    "t_cars",
-//                            "t_collect"
+//                                    "t_collect",
+//                            "t_pay_log"
                             )
                             // 设置过滤表前缀
                             .addTablePrefix("t_");

+ 9 - 6
miniapp/src/main/resources/application.yml

@@ -85,13 +85,16 @@ sa-token:
 # 微信支付
 wechat:
   payment:
-    app-id: wx369fcff95d387bde
+    appid: wx369fcff95d387bde
     # 微信商户号
-    meh-id: 1635831469
-    kch-key: SHENZHENKUAIYUMAN2O221229szkuaim
-    cert-path: /data/wwwroot/charge/config/cert/apiclient_cert.pem
-    key-path: /data/wwwroot/charge/config/cert/apiclient_key.pem
-    notify-url: https://www.kuaiyuman.cn/api/payment/notify
+    mchid: 1635831469
+    mchsn: 6A45EEB068369430B2FFD45EA29F641A8E18165F
+    v3Key: iTRovdvaTUQq0b9Jr91D7Tx66JnIes5U
+    notifyUrl: https://www.kuaiyuman.cn/api/payment/notify
+#    certPath: /data/wwwroot/charge/config/cert/apiclient_cert.pem
+#    keyPath: /data/wwwroot/charge/config/cert/apiclient_key.pem
+    certPath: D:/快与慢充电桩/微信支付证书/apiclient_cert.pem
+    keyPath: D:/快与慢充电桩/微信支付证书/apiclient_key.pem
 
   miniapp:
     appid: wx369fcff95d387bde

+ 0 - 21
miniapp/src/main/resources/mappers/AccountMapper.xml

@@ -1,21 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.kym.mapper.miniapp.AccountMapper">
-
-    <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.kym.entity.miniapp.Account">
-        <id column="id" property="id" />
-        <result column="user_id" property="userId" />
-        <result column="balance" property="balance" />
-        <result column="frozen_amount" property="frozenAmount" />
-        <result column="status" property="status" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
-    </resultMap>
-
-    <!-- 通用查询结果列 -->
-    <sql id="Base_Column_List">
-        id, user_id, balance, frozen_amount, status, create_time, update_time
-    </sql>
-
-</mapper>

+ 0 - 33
miniapp/src/main/resources/mappers/ChargeOrderMapper.xml

@@ -1,33 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.kym.mapper.miniapp.ChargeOrderMapper">
-
-    <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.kym.entity.miniapp.ChargeOrder">
-        <id column="id" property="id" />
-        <result column="user_id" property="userId" />
-        <result column="station_id" property="stationId" />
-        <result column="start_charge_seq" property="startChargeSeq" />
-        <result column="connector_id" property="connectorId" />
-        <result column="start_time" property="startTime" />
-        <result column="end_time" property="endTime" />
-        <result column="soc" property="soc" />
-        <result column="total_power" property="totalPower" />
-        <result column="total_money" property="totalMoney" />
-        <result column="elec_money" property="elecMoney" />
-        <result column="service_money" property="serviceMoney" />
-        <result column="sum_period" property="sumPeriod" />
-        <result column="charge_detail" property="chargeDetail" />
-        <result column="order_status" property="orderStatus" />
-        <result column="charge_status" property="chargeStatus" />
-        <result column="stop_reason" property="stopReason" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
-    </resultMap>
-
-    <!-- 通用查询结果列 -->
-    <sql id="Base_Column_List">
-        id, user_id, station_id, start_charge_seq, connector_id, start_time, end_time, soc, total_power, total_money, elec_money, service_money, sum_period, charge_detail, order_status, charge_status, stop_reason, create_time, update_time
-    </sql>
-
-</mapper>

+ 0 - 27
miniapp/src/main/resources/mappers/WalletDetailMapper.xml

@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.kym.mapper.miniapp.WalletDetailMapper">
-
-    <!-- 通用查询映射结果 -->
-    <resultMap id="BaseResultMap" type="com.kym.entity.miniapp.WalletDetail">
-        <id column="id" property="id" />
-        <result column="user_id" property="userId" />
-        <result column="type" property="type" />
-        <result column="current" property="current" />
-        <result column="order_no" property="orderNo" />
-        <result column="amount" property="amount" />
-        <result column="commission" property="commission" />
-        <result column="transaction_id" property="transactionId" />
-        <result column="transaction_time" property="transactionTime" />
-        <result column="status" property="status" />
-        <result column="remark" property="remark" />
-        <result column="create_time" property="createTime" />
-        <result column="update_time" property="updateTime" />
-    </resultMap>
-
-    <!-- 通用查询结果列 -->
-    <sql id="Base_Column_List">
-        id, user_id, type, current, order_no, amount, commission, transaction_id, transaction_time, status, remark, create_time, update_time
-    </sql>
-
-</mapper>

+ 7 - 0
service/pom.xml

@@ -24,12 +24,19 @@
             <artifactId>common</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
+
         <dependency>
             <groupId>com.kym</groupId>
             <artifactId>mapper</artifactId>
             <version>0.0.1-SNAPSHOT</version>
         </dependency>
 
+        <dependency>
+            <groupId>com.github.wechatpay-apiv3</groupId>
+            <artifactId>wechatpay-java</artifactId>
+            <version>0.2.11</version>
+        </dependency>
+
     </dependencies>
 
 </project>

+ 34 - 31
service/src/main/java/com/kym/service/enplus/impl/EnNotifyServiceImpl.java

@@ -100,11 +100,11 @@ public class EnNotifyServiceImpl implements EnNotifyService {
         var startChargeSeq = data.getString("StartChargeSeq");
         var chargeOrder = chargeOrderService.getChargingOrderByStartChargeSeq(startChargeSeq);
         // 更新订单信息
-        chargeOrder.setSoc(data.getBigDecimal("Soc"));
-        chargeOrder.setTotalPower(data.getBigDecimal("TotalPower"));
-        chargeOrder.setTotalMoney(data.getBigDecimal("TotalMoney"));
-        chargeOrder.setElecMoney(data.getBigDecimal("ElecMoney"));
-        chargeOrder.setServiceMoney(data.getBigDecimal("SeviceMoney")); // 这里文档service单词错误,按文档填写
+        chargeOrder.setSoc(data.getDoubleValue("Soc"));
+        chargeOrder.setTotalPower(data.getDoubleValue("TotalPower"));
+        chargeOrder.setTotalMoney(data.getIntValue("TotalMoney"));
+        chargeOrder.setElecMoney(data.getIntValue("ElecMoney"));
+        chargeOrder.setServiceMoney(data.getIntValue("SeviceMoney")); // 这里文档service单词错误,按文档填写
         chargeOrder.setSumPeriod(data.getIntValue("SumPeriod"));
         chargeOrder.setChargeDetail(data.getString("ChargeDetails"));
         chargeOrder.setChargeStatus(data.getIntValue("StartChargeSeqStat"));
@@ -158,33 +158,36 @@ public class EnNotifyServiceImpl implements EnNotifyService {
         var data = JSONObject.parseObject(dataStr);
         var startChargeSeq = data.getString("StartChargeSeq");
         var chargeOrder = chargeOrderService.getChargingOrderByStartChargeSeq(startChargeSeq);
-        // 更新订单信息
-        chargeOrder.setEndTime(LocalDateTime.parse(data.getString("EndTime"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-        chargeOrder.setTotalPower(data.getBigDecimal("TotalPower"));
-        chargeOrder.setElecMoney(data.getBigDecimal("TotalElecMoney"));
-        chargeOrder.setServiceMoney(data.getBigDecimal("TotalSeviceMoney")); // 这里文档service单词错误,按文档填写
-        chargeOrder.setTotalMoney(data.getBigDecimal("TotalMoney"));
-        chargeOrder.setStopReason(data.getIntValue("StopReason"));
-        chargeOrder.setSumPeriod(data.getIntValue("SumPeriod"));
-        chargeOrder.setChargeDetail(data.getString("ChargeDetails"));
-        chargeOrder.setOrderStatus(1);
-        chargeOrderService.updateById(chargeOrder);
+        // EN+平台推送重试策略是当天失败第二天再推送一次,仅此一次。EN+订单页面可以多次手动推送,所以这里要先判断订单状态,避免重复处理。
+        if (chargeOrder.getOrderStatus() != 4) {
+            // 更新订单信息
+            chargeOrder.setEndTime(LocalDateTime.parse(data.getString("EndTime"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+            chargeOrder.setTotalPower(data.getDoubleValue("TotalPower"));
+            chargeOrder.setElecMoney(data.getIntValue("TotalElecMoney"));
+            chargeOrder.setServiceMoney(data.getIntValue("TotalSeviceMoney")); // 这里文档service单词错误,按文档填写
+            chargeOrder.setTotalMoney(data.getIntValue("TotalMoney"));
+            chargeOrder.setStopReason(data.getIntValue("StopReason"));
+            chargeOrder.setSumPeriod(data.getIntValue("SumPeriod"));
+            chargeOrder.setChargeDetail(data.getString("ChargeDetails"));
+            chargeOrder.setOrderStatus(1);
+            chargeOrderService.updateById(chargeOrder);
+
 
-        // 扣费
-        var account = accountService.getAccountByUserId(chargeOrder.getUserId());
-        account.setBalance(account.getBalance().subtract(chargeOrder.getTotalMoney()));
-        accountService.save(account);
-
-        // 记录资金流水
-        var walletDetail = new WalletDetail();
-        walletDetail.setId(idGenerator.nextId());
-        walletDetail.setUserId(chargeOrder.getUserId());
-        walletDetail.setOrderNo(startChargeSeq);
-        walletDetail.setType(3);
-        walletDetail.setAmount(chargeOrder.getTotalMoney());
-        walletDetail.setTransactionTime(LocalDateTime.parse(data.getString("EndTime"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
-        walletDetail.setStatus(1);
-        walletDetailService.save(walletDetail);
+            // 扣费
+            var account = accountService.getAccountByUserId(chargeOrder.getUserId());
+            account.setBalance(account.getBalance() - chargeOrder.getTotalMoney());
+            accountService.updateById(account);
+
+            // 记录资金流水
+            var walletDetail = new WalletDetail();
+            walletDetail.setUserId(chargeOrder.getUserId());
+            walletDetail.setOrderNo(startChargeSeq);
+            walletDetail.setType(3);
+            walletDetail.setAmount(chargeOrder.getTotalMoney());
+            walletDetail.setTransactionTime(LocalDateTime.parse(data.getString("EndTime"), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+            walletDetail.setStatus(1);
+            walletDetailService.save(walletDetail);
+        }
         return """
                 {
                     "StartChargeSeq":%s,

+ 16 - 0
service/src/main/java/com/kym/service/miniapp/PayLogService.java

@@ -0,0 +1,16 @@
+package com.kym.service.miniapp;
+
+import com.kym.entity.miniapp.PayLog;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ * 支付日志 服务类
+ * </p>
+ *
+ * @author skyline
+ * @since 2023-08-12
+ */
+public interface PayLogService extends IService<PayLog> {
+
+}

+ 2 - 0
service/src/main/java/com/kym/service/miniapp/WalletDetailService.java

@@ -13,4 +13,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
  */
 public interface WalletDetailService extends IService<WalletDetail> {
 
+    WalletDetail getWalletDetailByOrderNo(String orderNo);
+
 }

+ 1 - 0
service/src/main/java/com/kym/service/miniapp/impl/ChargeOrderServiceImpl.java

@@ -25,4 +25,5 @@ public class ChargeOrderServiceImpl extends ServiceImpl<ChargeOrderMapper, Charg
         return getOne(lambdaQuery().eq(ChargeOrder::getStartChargeSeq,startChargeSeq));
     }
 
+
 }

+ 9 - 11
service/src/main/java/com/kym/service/miniapp/impl/ChargeServiceImpl.java

@@ -20,8 +20,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
-import java.math.BigDecimal;
-
 /**
  * @author skyline
  * @description 充电
@@ -80,12 +78,12 @@ public class ChargeServiceImpl implements ChargeService {
             }
             // 查询用户余额
             var account = accountService.getAccountByUserId(userId);
-            if (account.getBalance().compareTo(BigDecimal.valueOf(2L)) != 1) {
+            if (account.getBalance() <= 200) {
                 LOGGER.error("用户:{}余额不足2元,余额:{}", userId, account.getBalance());
                 throw new BusinessException(ResponseEnum.INSUFFICIENT_USER_BALANCE);
             }
             // 传递给EN+的余额要小于实际余额,防止订单超扣的情况,这里少传0.5元
-            var amount = account.getBalance().subtract(BigDecimal.valueOf(0.5));
+            var amount = account.getBalance() - 50;
 
             // 充电订单号/设备认证号
             String startChargeSeq = operatorId.substring(0, 8).concat(String.valueOf(idGenerator.nextId()));
@@ -147,7 +145,7 @@ public class ChargeServiceImpl implements ChargeService {
      * @param amount
      * @return
      */
-    public JSONObject queryStartCharge(String startChargeSeq, String connectorId, String qrCode, BigDecimal amount) {
+    public JSONObject queryStartCharge(String startChargeSeq, String connectorId, String qrCode, Integer amount) {
         var param = """
                 {
                     "StartChargeSeq":%s,
@@ -176,11 +174,11 @@ public class ChargeServiceImpl implements ChargeService {
             var data = enPlusService.queryEquipChargeStatus(startChargeSeq);
 
             // 更新订单信息
-            chargeOrder.setSoc(data.getBigDecimal("Soc"));
-            chargeOrder.setTotalPower(data.getBigDecimal("TotalPower"));
-            chargeOrder.setTotalMoney(data.getBigDecimal("TotalMoney"));
-            chargeOrder.setElecMoney(data.getBigDecimal("ElecMoney"));
-            chargeOrder.setServiceMoney(data.getBigDecimal("SeviceMoney")); // 这里文档service单词错误,按文档填写
+            chargeOrder.setSoc(data.getDoubleValue("Soc"));
+            chargeOrder.setTotalPower(data.getDoubleValue("TotalPower"));
+            chargeOrder.setTotalMoney(data.getIntValue("TotalMoney"));
+            chargeOrder.setElecMoney(data.getInteger("ElecMoney"));
+            chargeOrder.setServiceMoney(data.getInteger("SeviceMoney")); // 这里文档service单词错误,按文档填写
             chargeOrder.setSumPeriod(data.getIntValue("SumPeriod"));
             chargeOrder.setChargeDetail(data.getString("ChargeDetails"));
             chargeOrder.setChargeStatus(data.getIntValue("StartChargeSeqStat"));
@@ -206,7 +204,7 @@ public class ChargeServiceImpl implements ChargeService {
             connectorId = connectorId.concat("1");
         }
         var data = enPlusService.queryStopCharge(startChargeSeq, connectorId);
-        if (data.containsKey("SuccStat")&&data.getIntValue("SuccStat") != 0) {
+        if (data.containsKey("SuccStat") && data.getIntValue("SuccStat") != 0) {
             // 记录失败原因
             LOGGER.error("订单:{}停止充电失败,返回结果{}", startChargeSeq, data);
             throw new BusinessException(ResponseEnum.EN_PLUS_EQUIP_STOP_FAIL);

+ 20 - 0
service/src/main/java/com/kym/service/miniapp/impl/PayLogServiceImpl.java

@@ -0,0 +1,20 @@
+package com.kym.service.miniapp.impl;
+
+import com.kym.entity.miniapp.PayLog;
+import com.kym.mapper.miniapp.PayLogMapper;
+import com.kym.service.miniapp.PayLogService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ * 支付日志 服务实现类
+ * </p>
+ *
+ * @author skyline
+ * @since 2023-08-12
+ */
+@Service
+public class PayLogServiceImpl extends ServiceImpl<PayLogMapper, PayLog> implements PayLogService {
+
+}

+ 5 - 5
service/src/main/java/com/kym/service/miniapp/impl/UserServiceImpl.java

@@ -6,7 +6,7 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import com.kym.common.R;
-import com.kym.common.config.WxMiniAppConfig;
+import com.kym.common.config.WxConfig;
 import com.kym.common.constant.ResponseEnum;
 import com.kym.common.enums.WxApi;
 import com.kym.common.exception.BusinessException;
@@ -47,7 +47,7 @@ import static java.util.Map.of;
 public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
     private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
     @Autowired
-    WxMiniAppConfig wxMiniAppConfig;
+    WxConfig wxConfig;
     @Autowired
     private IDGenerator idGenerator;
     @Autowired
@@ -65,8 +65,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
     public R wxlogin(String code, String phoneCode, String avatar, String nickname) {
         // 微信登录
         var json = HttpUtil.getJson(WxApi.WX_MP_LOGIN.getApi(), Map.of(
-                "appid", wxMiniAppConfig.getAppId(),
-                "secret", wxMiniAppConfig.getSecret(),
+                "appid", wxConfig.getAppid(),
+                "secret", wxConfig.getSecret(),
                 "js_code", code
         ));
 
@@ -90,7 +90,7 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
                 newUser.setUnionid(unionid);
                 // 手机号解密:先获取access_token,再请求手机号信息
                 // access_token获取
-                var accessTokenJson = HttpUtil.getJson(WxApi.WX_GET_ACCESS_TOKEN.getApi(), Map.of("appid", wxMiniAppConfig.getAppId(), "secret", wxMiniAppConfig.getSecret()));
+                var accessTokenJson = HttpUtil.getJson(WxApi.WX_GET_ACCESS_TOKEN.getApi(), Map.of("appid", wxConfig.getAppid(), "secret", wxConfig.getSecret()));
                 var accessToken = accessTokenJson.getString("access_token");
                 var wxPhoneNum = HttpUtil.post(WxApi.WX_MP_GET_PHONE.getApi().replace("ACCESS_TOKEN", accessToken), Map.of("code", code), WxPhoneNum.class);
                 var mobilePhone = wxPhoneNum.getPhone_info().getPurePhoneNumber();

+ 6 - 1
service/src/main/java/com/kym/service/miniapp/impl/WalletDetailServiceImpl.java

@@ -1,9 +1,9 @@
 package com.kym.service.miniapp.impl;
 
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.kym.entity.miniapp.WalletDetail;
 import com.kym.mapper.miniapp.WalletDetailMapper;
 import com.kym.service.miniapp.WalletDetailService;
-import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import org.springframework.stereotype.Service;
 
 /**
@@ -17,4 +17,9 @@ import org.springframework.stereotype.Service;
 @Service
 public class WalletDetailServiceImpl extends ServiceImpl<WalletDetailMapper, WalletDetail> implements WalletDetailService {
 
+
+    @Override
+    public WalletDetail getWalletDetailByOrderNo(String orderNo) {
+        return getOne(lambdaQuery().eq(WalletDetail::getOrderNo, orderNo));
+    }
 }

+ 14 - 0
service/src/main/java/com/kym/service/wechat/WxPayService.java

@@ -0,0 +1,14 @@
+package com.kym.service.wechat;
+
+import com.wechat.pay.java.service.payments.jsapi.model.PrepayResponse;
+
+import java.math.BigDecimal;
+
+/**
+ * @author skyline
+ * @description
+ * @date 2023-08-11 19:05
+ */
+public interface WxPayService {
+    PrepayResponse prepay(BigDecimal rechargeAmount, String openid);
+}

+ 203 - 0
service/src/main/java/com/kym/service/wechat/impl/WxPayServiceImpl.java

@@ -0,0 +1,203 @@
+package com.kym.service.wechat.impl;
+
+import com.kym.common.config.WxPayConfig;
+import com.kym.common.utils.OrderUtils;
+import com.kym.entity.miniapp.PayLog;
+import com.kym.service.miniapp.PayLogService;
+import com.kym.service.miniapp.WalletDetailService;
+import com.kym.service.wechat.WxPayService;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.core.exception.ValidationException;
+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.*;
+import com.wechat.pay.java.service.payments.model.Transaction;
+import jakarta.annotation.PostConstruct;
+import jakarta.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.stereotype.Service;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.math.BigDecimal;
+
+/**
+ * @author skyline
+ * @description 微信支付
+ * @date 2023-08-10 14:03
+ */
+@Service
+public class WxPayServiceImpl implements WxPayService {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(WxPayServiceImpl.class);
+
+    public static JsapiService service;
+
+    public static Config config;
+
+    @Autowired
+    private WxPayConfig conf;
+
+    @Autowired
+    private WalletDetailService walletDetailService;
+
+    @Autowired
+    private PayLogService payLogService;
+
+    /**
+     * 商户订单号查询订单
+     */
+    public static Transaction queryOrderByOutTradeNo() {
+
+        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
+        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+        // 调用接口
+        return service.queryOrderByOutTradeNo(request);
+    }
+
+
+    @PostConstruct
+    void init() {
+        config = new RSAAutoCertificateConfig.Builder()
+                .merchantId(conf.getMchid()) // 商户号
+                .privateKeyFromPath(conf.getKeyPath()) // 商户API私钥路径
+                .merchantSerialNumber(conf.getMchsn()) // 商户证书序列号
+                .apiV3Key(conf.getV3key()) // 商户APIV3密钥
+                .build();
+        service = new JsapiService.Builder().config(config).build();
+    }
+
+    /**
+     * JSAPI支付下单
+     */
+    @Override
+    public PrepayResponse prepay(BigDecimal rechargeAmount, String openid) {
+        // 生成订单号
+        String outTradeNo = OrderUtils.getOrderNo();
+        // request.setXxx(val)设置所需参数,具体参数可见Request定义
+        PrepayRequest request = new PrepayRequest();
+        Amount amount = new Amount();
+        amount.setTotal(rechargeAmount.multiply(new BigDecimal(100)).intValue());
+        request.setAmount(amount);
+        request.setAppid(conf.getAppid());
+        request.setMchid(conf.getMchid());
+        request.setDescription("K7充电生活充值");
+        request.setNotifyUrl(conf.getNotifyUrl());
+        request.setOutTradeNo(outTradeNo);
+        Payer payer = new Payer();
+        payer.setOpenid(openid);
+        request.setPayer(payer);
+        return service.prepay(request);
+    }
+
+    /**
+     * 微信支付订单号查询订单
+     */
+    public Transaction queryOrderById(String transactionId) {
+        QueryOrderByIdRequest request = new QueryOrderByIdRequest();
+        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+        request.setMchid(conf.getMchid());
+        request.setTransactionId(transactionId);
+        // 调用接口
+        return service.queryOrderById(request);
+    }
+
+    /**
+     * 关闭订单
+     */
+    public void closeOrder(String outTradeNo) {
+        CloseOrderRequest request = new CloseOrderRequest();
+        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+        request.setMchid(conf.getMchid());
+        request.setOutTradeNo(outTradeNo);
+        // 调用接口
+        service.closeOrder(request);
+    }
+
+    public ResponseEntity.BodyBuilder wxNotify(HttpServletRequest request) throws IOException {
+        var signature = request.getHeader("Wechatpay-Signature");
+        var serial = request.getHeader("Wechatpay-Serial");
+        var nonce = request.getHeader("Wechatpay-Nonce");
+        var timestamp = request.getHeader("Wechatpay-Timestamp");
+        var signatureType = request.getHeader("Wechatpay-Signature-Type");
+
+        // request中获取body
+        BufferedReader br = request.getReader();
+        String str;
+        var requestBody = new StringBuilder();
+        while ((str = br.readLine()) != null) {
+            requestBody.append(str);
+
+
+            // 构造 RequestParam
+            RequestParam requestParam = new RequestParam.Builder()
+                    .serialNumber(serial)
+                    .nonce(nonce) // 随机数
+                    .signature(signature)
+                    .timestamp(timestamp)
+                    .body(requestBody.toString())
+                    .build();
+
+
+            // 如果已经初始化了 RSAAutoCertificateConfig,可直接使用
+            // 初始化 NotificationParser
+            NotificationParser parser = new NotificationParser((NotificationConfig) config);
+
+            try {
+                // 以支付通知回调为例,验签、解密并转换成 Transaction
+                Transaction transaction = parser.parse(requestParam, Transaction.class);
+                // 判断是否已经接收处理过通知
+                if (payLogService.getOne(payLogService.lambdaQuery().eq(PayLog::getOutTradeNo, transaction.getOutTradeNo())) != null) {
+                    return ResponseEntity.status(HttpStatus.OK);
+                }
+
+                // 资金流水
+                var walletDetail = walletDetailService.getWalletDetailByOrderNo(transaction.getOutTradeNo());
+                if (walletDetail != null) {
+                    walletDetail.setType(1); // 充值
+                    walletDetail.setStatus(1);  //已确认
+                    walletDetail.setCurrency(transaction.getAmount().getCurrency());
+                    walletDetail.setAmount(transaction.getAmount().getTotal());
+
+                    // 支付记录
+                    var payLog = new PayLog();
+                    payLog.setUserId(walletDetail.getUserId());
+                    payLog.setOpenid(transaction.getPayer().getOpenid());
+                    payLog.setBankType(transaction.getBankType());
+                    payLog.setMchId(transaction.getMchid());
+                    payLog.setOutTradeNo(transaction.getOutTradeNo());
+                    payLog.setTransactionId(transaction.getTransactionId());
+                    payLog.setSuccessTime(transaction.getSuccessTime());
+                    payLog.setTradeType(transaction.getTradeType().name());
+                    payLog.setTradeState(transaction.getTradeState().name());
+                    payLog.setAttach(transaction.getAttach());
+                    payLog.setTotal(transaction.getAmount().getTotal());
+                    payLog.setCurrency(transaction.getAmount().getCurrency());
+                    payLog.setPayerTotal(transaction.getAmount().getPayerTotal());
+                    payLog.setPayerCurrency(transaction.getAmount().getPayerCurrency());
+                    payLogService.save(payLog);
+
+                } else {
+                    LOGGER.error("微信支付通知处理异常,资金流水为空,回调信息:{}", transaction);
+                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR);
+                }
+
+            } catch (ValidationException e) {
+                // 签名验证失败,返回 401 UNAUTHORIZED 状态码
+                LOGGER.error("微信支付通知眼前失败", e);
+                throw e;
+            }
+
+        }
+
+        // 处理成功,返回 200 OK 状态码
+        return ResponseEntity.status(HttpStatus.OK);
+    }
+}