skyline 2 лет назад
Родитель
Сommit
af5070237e

+ 1 - 0
common/src/main/java/com/kym/common/constant/ResponseEnum.java

@@ -14,6 +14,7 @@ public enum ResponseEnum implements BusinessExceptionAssert {
     FAILED(500, "failed"),
 
     HTTP_STATUS_200(200, "ok"),
+    HTTP_STATUS_202(202, "accepted"),
     HTTP_STATUS_400(400, "request error"),
     HTTP_STATUS_401(401, "no authentication"),
     HTTP_STATUS_403(403, "no authorities"),

+ 4 - 0
entity/pom.xml

@@ -65,6 +65,10 @@
             <artifactId>pagehelper-spring-boot-starter</artifactId>
             <version>1.4.7</version>
         </dependency>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
 
     </dependencies>
     <!-- 空间处理这几个依赖单独仓库下载 -->

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

@@ -1,6 +1,9 @@
 package com.kym.entity.miniapp;
 
+import com.alibaba.fastjson2.JSONObject;
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
 import com.kym.entity.BaseEntity;
 import java.io.Serializable;
 import lombok.Getter;
@@ -18,15 +21,18 @@ import lombok.Setter;
 @Setter
 @TableName("t_invoice")
 public class Invoice extends BaseEntity {
-
     private static final long serialVersionUID = 1L;
 
+    public static final String TYPE_个人 = "INDIVIDUAL";
+    public static final String TYPE_企业 = "ORGANIZATION";
+
     private Long userId;
 
     /**
-     * 充电订单号(EN+)
+     * 发票关联订单详情
      */
-    private String startChargeSeq;
+    @TableField(typeHandler = JacksonTypeHandler.class)
+    private JSONObject orderDetails;
 
     /**
      * 累积充电量(度)
@@ -54,9 +60,9 @@ public class Invoice extends BaseEntity {
     private String email;
 
     /**
-     * 发票类型:0-个人 1-企业
+     * 发票类型:INDIVIDUAL-个人 ORGANIZATION-企业
      */
-    private Byte invoiceType;
+    private int invoiceType;
 
     /**
      * 发票抬头

+ 77 - 0
entity/src/main/java/com/kym/entity/wechat/InvoiceNotification.java

@@ -0,0 +1,77 @@
+package com.kym.entity.wechat;
+
+import com.google.gson.annotations.SerializedName;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author skyline
+ * @description 微信发票回调通知
+ * @date 2023-09-17 11:30
+ */
+@Data
+public class InvoiceNotification {
+
+    /**
+     * 微信支付分配的商户号
+     */
+    @SerializedName("mchid")
+    private String mchid;
+
+    /**
+     * 开票时指定的发票申请单号
+     */
+    @SerializedName("fapiao_apply_id")
+    private String fapiaoApplyId;
+
+    @SerializedName("fapiao_information")
+    private List<FapiaoInformation> fapiaoInformation;
+
+
+    /**
+     * 发票状态
+     */
+    enum FapiaoStatus {
+        ISSUE_ACCEPTED, ISSUED, REVERSE_ACCEPTED, REVERSED
+    }
+
+
+    /**
+     * 发票状态-卡包状态
+     */
+    enum CardStatus {
+        INSERT_ACCEPTED, INSERTED, DISCARD_ACCEPTED, DISCARDED
+    }
+
+    @Data
+    class FapiaoInformation {
+
+        /**
+         * 商户发票单号,唯一标识一张发票
+         */
+        @SerializedName("fapiao_id")
+        private String fapiaoId;
+
+        /**
+         * 发票状态,枚举值:
+         * ISSUE_ACCEPTED:开票请求已受理
+         * ISSUED:发票已开具
+         * REVERSE_ACCEPTED:冲红申请已受理
+         * REVERSED:发票已冲红
+         */
+        @SerializedName("fapiao_status")
+        private String fapiaoStatus;
+
+        /**
+         * 发票状态,枚举值:
+         * INSERT_ACCEPTED:已插入用户卡包
+         * INSERTED:插卡已受理
+         * DISCARD_ACCEPTED:作废申请已受理
+         * DISCARDED:发票卡券已作废
+         */
+        @SerializedName("card_status")
+        private String cardStatus;
+
+    }
+}

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

@@ -5,7 +5,7 @@
     <!-- 通用查询映射结果 -->
     <resultMap id="BaseResultMap" type="com.kym.entity.miniapp.Invoice">
         <result column="user_id" property="userId" />
-        <result column="start_charge_seq" property="startChargeSeq" />
+        <result column="orderDetails" property="order_details" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler" />
         <result column="total_power" property="totalPower" />
         <result column="total_money" property="totalMoney" />
         <result column="elec_money" property="elecMoney" />
@@ -21,7 +21,7 @@
 
     <!-- 通用查询结果列 -->
     <sql id="Base_Column_List">
-        id,user_id, start_charge_seq, total_power, total_money, elec_money, service_money, email, invoice_type, invoice_title, tax_id, invoice_amount, tax_info, biller,remark,create_time,update_time
+        id,user_id, order_details, total_power, total_money, elec_money, service_money, email, invoice_type, invoice_title, tax_id, invoice_amount, tax_info, biller,remark,create_time,update_time
     </sql>
 
 </mapper>

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

@@ -21,6 +21,7 @@ import com.kym.entity.miniapp.RefundLog;
 import com.kym.entity.miniapp.WalletDetail;
 import com.kym.entity.wechat.FaPiao;
 import com.kym.entity.wechat.InvoiceBaseInfo;
+import com.kym.entity.wechat.InvoiceNotification;
 import com.kym.entity.wechat.TaxCodes;
 import com.kym.service.miniapp.*;
 import com.kym.service.wechat.WxPayService;
@@ -131,6 +132,15 @@ public class WxPayServiceImpl implements WxPayService {
         refundService = new RefundService.Builder().config(config).build();
     }
 
+
+    /**
+     * 处理微信回调信息,验签解密
+     *
+     * @param request
+     * @return array[0] RequestParam 请求参数
+     * array[1] NotificationParser 通知解析器
+     * array[2] nonce 随机数
+     */
     @SneakyThrows
     Object[] handleWxNotify(HttpServletRequest request) {
         var no = RandomUtil.randomInt(1000, 9999);
@@ -557,4 +567,25 @@ public class WxPayServiceImpl implements WxPayService {
         var res = HttpUtil.post(url, JSONObject.toJSONString(fapiao), headers);
     }
 
+    /**
+     * 微信开票结果通知
+     *
+     * @param request
+     * @return
+     */
+    void wxInvoiceNotify(HttpServletRequest request) {
+        var notifyRes = handleWxNotify(request);
+        try {
+            InvoiceNotification invoiceNotification = ((NotificationParser) notifyRes[1]).parse((RequestParam) notifyRes[0], InvoiceNotification.class);
+            LOGGER.info("微信开具发票结果通知回调{}:验签解密完毕,数据:\n{}", notifyRes[2], invoiceNotification);
+            // TODO: 2023-09-17 业务逻辑
+
+        }  catch (ValidationException e) {
+            // 签名验证失败,返回 401 UNAUTHORIZED 状态码
+            LOGGER.error("微信开具发票结果通知验签失败", e);
+            throw new BusinessException("验签失败");
+        }
+    }
+
+
 }