Selaa lähdekoodia

封装微信支付业务

lighter 1 vuosi sitten
vanhempi
commit
7fd0c594df

+ 66 - 71
src/main/java/thyyxxk/wxservice_server/api/WxAppletApi.java

@@ -2,9 +2,6 @@ package thyyxxk.wxservice_server.api;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
-import com.wechat.pay.java.core.Config;
-import com.wechat.pay.java.service.payments.jsapi.JsapiService;
-import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
 import com.wechat.pay.java.service.payments.jsapi.model.*;
 import com.wechat.pay.java.service.payments.model.Transaction;
 import lombok.extern.slf4j.Slf4j;
@@ -23,6 +20,7 @@ import thyyxxk.wxservice_server.entity.appointment.DoctorInfo;
 import thyyxxk.wxservice_server.entity.appointment.PatientBriefInfo;
 import thyyxxk.wxservice_server.entity.collections.CollectDoctorParam;
 import thyyxxk.wxservice_server.entity.electronichealthcard.ElectronicHealthCard;
+import thyyxxk.wxservice_server.entity.hrgresponse.HrgCommonResponse;
 import thyyxxk.wxservice_server.entity.hrgresponse.SourcesResponse;
 import thyyxxk.wxservice_server.entity.inpatient.GetZyFeeParam;
 import thyyxxk.wxservice_server.entity.inpatient.InpatientInfo;
@@ -31,9 +29,10 @@ import thyyxxk.wxservice_server.entity.patientcards.ModifyBindParam;
 import thyyxxk.wxservice_server.entity.wxapi.wxapplet.request.*;
 import thyyxxk.wxservice_server.entity.wxapi.wxapplet.response.AppletMallCart;
 import thyyxxk.wxservice_server.entity.wxapi.wxapplet.response.WxAppletOrder;
+import thyyxxk.wxservice_server.factory.wechatpay.WeChatPayService;
+import thyyxxk.wxservice_server.factory.wechatpay.model.WechatPayGlobalRequest;
 import thyyxxk.wxservice_server.service.*;
 import thyyxxk.wxservice_server.utils.*;
-import thyyxxk.wxservice_server.utils.wxpay.WxPayConfigUtil;
 
 import java.io.File;
 import java.math.BigDecimal;
@@ -50,28 +49,25 @@ public class WxAppletApi {
     private final InpatientService inpatientService;
     private final SaveAppletPayResultService saveAppletPayResultService;
     private final CollectionsService collectionsService;
-    private final WxApiService wxApiService;
     private final AppletDao appletDao;
     private final PatientCardsDao cardsDao;
     private final InpatientDao inpatientDao;
     private final AppointmentDao appointmentDao;
     private final WxApiDao wxApiDao;
+    private final static String GET_USER_INFO = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
     @Value("${hrgApiUrl}")
     private String hrgApiUrl;
-    private final static String GET_USER_INFO = "https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code";
-
     @Value("${appletThmzUrl}")
     String appletThmzUrl;
     
     @Autowired
-    public WxAppletApi(IdCardAnalyzeService idCardAnalyzeService, WxRefundService wxRefundService, ElectronicHealthCardService electronicHealthCardService, InpatientService inpatientService, SaveAppletPayResultService saveAppletPayResultService, CollectionsService collectionsService, WxApiService wxApiService, AppletDao dao, PatientCardsDao cardsDao, InpatientDao inpatientDao, AppointmentDao appointmentDao, WxApiDao wxApiDao) {
+    public WxAppletApi(IdCardAnalyzeService idCardAnalyzeService, WxRefundService wxRefundService, ElectronicHealthCardService electronicHealthCardService, InpatientService inpatientService, SaveAppletPayResultService saveAppletPayResultService, CollectionsService collectionsService, AppletDao dao, PatientCardsDao cardsDao, InpatientDao inpatientDao, AppointmentDao appointmentDao, WxApiDao wxApiDao) {
         this.idCardAnalyzeService = idCardAnalyzeService;
         this.wxRefundService = wxRefundService;
         this.electronicHealthCardService = electronicHealthCardService;
         this.inpatientService = inpatientService;
         this.saveAppletPayResultService = saveAppletPayResultService;
         this.collectionsService = collectionsService;
-        this.wxApiService = wxApiService;
         this.appletDao = dao;
         this.cardsDao = cardsDao;
         this.inpatientDao = inpatientDao;
@@ -119,63 +115,49 @@ public class WxAppletApi {
         if (StringUtil.isBlank(order.getDescription())) {
             return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "商品描述不能为空。");
         }
-        String appId = appletType == AppletType.HOSPITAL_SERVICE ?
-                PropertiesUtil.getLocalProperty("appletAppId") :
-                PropertiesUtil.getLocalProperty("appletMallAppId");
-        String mchId = PropertiesUtil.getLocalProperty("mchId");
-        String tradeNo = SnowFlakeId.instance().nextWxAppletTradeNo();
-        Config config = WxPayConfigUtil.getInstance().getConfig();
-        JsapiServiceExtension service = new JsapiServiceExtension.Builder().config(config).build();
-        PrepayRequest request = new PrepayRequest();
-        Amount amount = new Amount();
-        amount.setTotal(order.getTotalAmount());
-        request.setAmount(amount);
-        request.setDescription(order.getDescription());
-        request.setAppid(appId);
-        request.setMchid(mchId);
-        request.setNotifyUrl(PropertiesUtil.getLocalProperty("jsapiNotifyUrl"));
-        request.setOutTradeNo(tradeNo);
-        Payer payer = new Payer();
-        payer.setOpenid(order.getOpenId());
-        request.setPayer(payer);
-        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
-        order.setPrepayId(response.getPackageVal());
-        order.setPayment(response);
-        order.setAppId(appId);
-        order.setMchId(mchId);
-        order.setTradeNo(tradeNo);
+
+        order.setMchId(PropertiesUtil.getLocalProperty("mchId"));
         order.setSerialNo(SnowFlakeId.instance().nextId());
-        log.info("小程序支付下单:\n{}", JSONObject.toJSON(order));
-        if (ListUtil.notEmpty(order.getCartIdList())) {
-            StringBuilder sb = new StringBuilder(",");
-            for (int cartId : order.getCartIdList()) {
-                sb.append(cartId).append(",");
-            }
-            order.setCartIds(sb.toString());
-        } else {
-            order.setCartIds("");
-        }
+        order.setTradeNo(SnowFlakeId.instance().nextWxAppletTradeNo());
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .appletType(appletType).outTradeNo(order.getTradeNo())
+                .openId(order.getOpenId()).description(order.getDescription())
+                .totalAmount(order.getTotalAmount()).build();
+        PrepayWithRequestPaymentResponse response = new WeChatPayService().jsApiPrepay(request);
+        order.setPayment(response);
+        order.setAppId(response.getAppId());
+        order.setPrepayId(response.getPackageVal());
+        cartIdList2String(order);
         appletDao.insertNewOrder(order);
         return ResultVoUtil.success(order);
     }
 
+    private void cartIdList2String(WxAppletOrder order) {
+        if (ListUtil.isEmpty(order.getCartIdList())) {
+            order.setCartIds("");
+            return;
+        }
+        StringBuilder sb = new StringBuilder(",");
+        for (int cartId : order.getCartIdList()) {
+            sb.append(cartId).append(",");
+        }
+        order.setCartIds(sb.toString());
+    }
+
     public void closeWxOrder(BaseInquiry inquiry) {
         String tradeNo = inquiry.getTradeNo();
         if (StringUtil.notBlank(tradeNo)) {
-            wxApiService.executeCloseOrder(tradeNo);
-            log.info("关闭微信订单:{}", tradeNo);
+            WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                    .outTradeNo(tradeNo).build();
+            new WeChatPayService().closeOrder(request);
             appletDao.updatePayStatusOnly(tradeNo, Transaction.TradeStateEnum.CLOSED);
         }
     }
 
     private Transaction queryOrderStateFromTencent(String tradeNo) {
-        Config config = WxPayConfigUtil.getInstance().getConfig();
-        JsapiService service = new JsapiService.Builder().config(config).build();
-        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
-        request.setMchid(PropertiesUtil.getLocalProperty("mchId"));
-        request.setOutTradeNo(tradeNo);
-        Transaction transaction = service.queryOrderByOutTradeNo(request);
-        log.info("小程序查询订单状态【{}】:{}", tradeNo, transaction);
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .outTradeNo(tradeNo).build();
+        Transaction transaction = new WeChatPayService().queryOrderState(request);
         Transaction.TradeStateEnum state = transaction.getTradeState();
         appletDao.updateQueryTimes(tradeNo);
         if (state != Transaction.TradeStateEnum.NOTPAY) {
@@ -267,6 +249,12 @@ public class WxAppletApi {
 
     @PostMapping("/addItemToCart")
     public ResultVo<Integer> addItemToCart(@RequestBody AppletMallCart cart) {
+        if (null == cart.getTemplatePrice()) {
+            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "套餐单价不能为空。");
+        }
+        if (null == cart.getTemplateAmount()) {
+            return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "套餐数量不能为空。");
+        }
         log.info("添加购物车:{}", JSONObject.toJSON(cart));
         String serialNo = SnowFlakeId.instance().nextId();
         cart.setSerialNo(serialNo);
@@ -293,7 +281,7 @@ public class WxAppletApi {
     }
 
     @PostMapping("/revokeCart")
-    public ResultVo<String> revokeCart(@RequestBody AppletMallCart cart) throws Exception {
+    public ResultVo<String> revokeCart(@RequestBody AppletMallCart cart) {
         if (StringUtil.isBlank(cart.getOpenId())) {
             return ResultVoUtil.fail(ExceptionEnum.NULL_POINTER, "openId不能为空。");
         }
@@ -307,27 +295,32 @@ public class WxAppletApi {
             appletDao.updateCartTradeStateById(cart.getId(), Transaction.TradeStateEnum.REVOKED);
             return ResultVoUtil.success("订单已取消。");
         }
-
         if (StringUtil.isBlank(cart.getRefundReason())) {
-            existCart.setRefundReason("");
+            existCart.setRefundReason("自助撤销订单");
         }
 
+        existCart.setPsOrdNum(order.getTradeNo());
+        existCart.setAgtOrdNum(order.getSerialNo());
+        HrgCommonResponse response = revokeTemplateFromHis(existCart);
+        if (null == response) {
+            return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
+        }
+        if (null == response.getCode() || 0 != response.getCode()) {
+            return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, response.getMessage());
+        }
         BigDecimal totalFee = DecimalTool.multiply(existCart.getTemplatePrice(),
                 new BigDecimal(existCart.getTemplateAmount()));
         order.setRefundAmount(DecimalTool.moneyYuanToFen(totalFee).intValue());
-
         ResultVo<WxAppletOrder> refundResult = wxRefundService.wxAppletRefund(order);
         if (refundResult.getCode() != ExceptionEnum.SUCCESS.getCode()) {
             return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, refundResult.getMessage());
         }
-
         WxAppletOrder refundedOrder = refundResult.getData();
         if (Objects.equals(refundedOrder.getTotalAmount(), refundedOrder.getRefundAmount())) {
             order.setRefundOpDatetime(new Date());
             order.setRefundReason(existCart.getRefundReason());
             appletDao.updateOrderRefundState(order);
         }
-
         existCart.setRefundId(order.getRefundId());
         existCart.setRefundOpCode(cart.getOpenId());
         existCart.setRefundDateTime(refundedOrder.getRefundOpDatetime());
@@ -337,6 +330,20 @@ public class WxAppletApi {
         return ResultVoUtil.success("订单已取消");
     }
 
+    private HrgCommonResponse revokeTemplateFromHis(AppletMallCart cart) {
+        JSONArray array = new JSONArray();
+        JSONObject params = new JSONObject();
+        params.put("patientId", cart.getPatientId());
+        params.put("templateId", cart.getTemplateId());
+        params.put("psOrdNum", cart.getPsOrdNum());
+        params.put("agtOrdNum", cart.getAgtOrdNum());
+        array.add(params);
+        String url = hrgApiUrl + "/tcRefundFee";
+        HrgCommonResponse response = new RestTemplate().postForObject(url, array, HrgCommonResponse.class);
+        log.info("HIS撤销套餐:\n参数:{}\n结果:{}", array, JSONObject.toJSON(response));
+        return response;
+    }
+
     @PostMapping("/queryTcDepartment")
     public ResultVo<JSONArray> queryTcDepartment() {
         String url = appletThmzUrl + "/queryTcDiscuntDept";
@@ -654,16 +661,4 @@ public class WxAppletApi {
         return collectionsService.getMyCollections(openId);
     }
 
-    @GetMapping("/test")
-    public ResultVo<Object> test() {
-        WxAppletOrder order = new WxAppletOrder();
-        order.setPatientId("317452-0");
-        order.setCartIds(",2289,2290,2293,");
-        order.setTradeNo(SnowFlakeId.instance().nextWxAppletTradeNo());
-        order.setTotalAmount(335100);
-        order.setSerialNo(String.valueOf(System.currentTimeMillis()));
-        order.setPayDatetime(new Date());
-        return saveAppletPayResultService.saveTemplateInfo(order);
-    }
-
 }

+ 3 - 5
src/main/java/thyyxxk/wxservice_server/controller/WxApiController.java

@@ -7,7 +7,6 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 import thyyxxk.wxservice_server.entity.ResultVo;
 import thyyxxk.wxservice_server.entity.appointment.DoctorInfo;
-import thyyxxk.wxservice_server.entity.appointment.WeChatPayParam;
 import thyyxxk.wxservice_server.entity.wxapi.*;
 import thyyxxk.wxservice_server.service.WxRefundService;
 import thyyxxk.wxservice_server.service.PushWxMessageService;
@@ -50,10 +49,9 @@ public class WxApiController {
     }
 
     @PostMapping("/createPayOrder")
-    public ResultVo<WxPayOrder> createPayOrder(HttpServletRequest request,
-                                               @RequestBody @Validated WeChatPayParam param) {
-        param.setClientIp(request.getRemoteAddr());
-        return service.createPayOrder(param);
+    public ResultVo<WxPayOrder> createPayOrder(HttpServletRequest request, @RequestBody WxPayOrder order) {
+        order.setSpbillCreateIp(request.getRemoteHost());
+        return service.createPayOrder(order);
     }
 
     @GetMapping("/queryOrderState")

+ 6 - 2
src/main/java/thyyxxk/wxservice_server/controller/WxPayNotifyController.java

@@ -5,6 +5,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
+import thyyxxk.wxservice_server.factory.wechatpay.WeChatPayService;
+import thyyxxk.wxservice_server.factory.wechatpay.model.WechatPayGlobalRequest;
 import thyyxxk.wxservice_server.service.WxPayNotifyService;
 
 import javax.servlet.http.HttpServletRequest;
@@ -29,7 +31,9 @@ public class WxPayNotifyController {
     }
 
     @PostMapping("/jsapi")
-    public void paymentNotify3(HttpServletRequest request) throws Exception {
-        service.jsapiNotify(request);
+    public void paymentNotify3(HttpServletRequest httpServletRequest) {
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .httpServletRequest(httpServletRequest).build();
+        new WeChatPayService().decryptNotify(request);
     }
 }

+ 8 - 0
src/main/java/thyyxxk/wxservice_server/dao/AppletDao.java

@@ -130,4 +130,12 @@ public interface AppletDao {
             "</foreach>" +
             "</script>")
     List<Integer> selectTemplateIds(List<Integer> idList);
+
+    @Select("<script>" +
+            "select template_id from t_applet_mall_cart where id in " +
+            "<foreach collection='idList' item='id' open='(' separator=',' close=')'> " +
+            "#{id}" +
+            "</foreach>" +
+            "</script>")
+    List<Integer> selectTemplateIdsByCartIdArray(String[] idList);
 }

+ 0 - 35
src/main/java/thyyxxk/wxservice_server/entity/appointment/WeChatPayParam.java

@@ -1,35 +0,0 @@
-package thyyxxk.wxservice_server.entity.appointment;
-
-import lombok.Data;
-
-import javax.validation.constraints.DecimalMin;
-import javax.validation.constraints.NotBlank;
-import javax.validation.constraints.NotNull;
-import java.math.BigDecimal;
-
-/**
- * @author dj
- */
-@Data
-public class WeChatPayParam {
-    @NotBlank(message = "商品描述不能为空")
-    private String body;
-    /**
-     * 订单类型,1:挂号费 2:门诊缴费 3:住院预交金 0:诊间挂号
-     * */
-    @NotNull(message = "订单类型不能为空")
-    private Integer orderType;
-    @NotBlank(message = "openId不能为空")
-    private String openId;
-    @DecimalMin(value = "0", message = "订单金额需要大于零")
-    private BigDecimal totalFee;
-    private String clientIp;
-    @NotBlank(message = "门诊id不能为空")
-    private String patientId;
-    private String hisOrdNum;
-    private Integer mzyRequestId;
-    private String apTime;
-    private Integer yjReqNo;
-    private String inpatientNo;
-    private Integer admissTimes;
-}

+ 2 - 0
src/main/java/thyyxxk/wxservice_server/entity/wxapi/wxapplet/response/AppletMallCart.java

@@ -22,5 +22,7 @@ public class AppletMallCart {
     private String refundOpCode;
     private Date refundDateTime;
     private String refundReason;
+    private String psOrdNum;
+    private String agtOrdNum;
     private Transaction.TradeStateEnum tradeState;
 }

+ 180 - 0
src/main/java/thyyxxk/wxservice_server/factory/wechatpay/WeChatPayService.java

@@ -0,0 +1,180 @@
+package thyyxxk.wxservice_server.factory.wechatpay;
+
+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.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.JsapiServiceExtension;
+import com.wechat.pay.java.service.payments.jsapi.model.*;
+import com.wechat.pay.java.service.payments.model.Transaction;
+import com.wechat.pay.java.service.payments.nativepay.NativePayService;
+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 lombok.extern.slf4j.Slf4j;
+import thyyxxk.wxservice_server.entity.wxapi.RefundResponse;
+import thyyxxk.wxservice_server.entity.wxapi.wxapplet.request.AppletType;
+import thyyxxk.wxservice_server.factory.wechatpay.model.NativePayResponse;
+import thyyxxk.wxservice_server.factory.wechatpay.model.WechatPayGlobalRequest;
+import thyyxxk.wxservice_server.utils.PropertiesUtil;
+import thyyxxk.wxservice_server.utils.SnowFlakeId;
+import thyyxxk.wxservice_server.utils.wxpay.WxPayConfigUtil;
+
+import javax.servlet.http.HttpServletRequest;
+import java.io.BufferedReader;
+import java.io.IOException;
+
+@Slf4j
+public class WeChatPayService {
+
+    public PrepayWithRequestPaymentResponse jsApiPrepay(WechatPayGlobalRequest request) {
+        Config config = WxPayConfigUtil.getInstance().getConfig();
+        JsapiServiceExtension service = new JsapiServiceExtension.Builder()
+                .config(config).build();
+        PrepayRequest prepayRequest = new PrepayRequest();
+        Amount amount = new Amount();
+        amount.setTotal(request.getTotalAmount());
+        prepayRequest.setAmount(amount);
+        prepayRequest.setDescription(request.getDescription());
+        prepayRequest.setAppid(getAppIdByAppletType(request.getAppletType()));
+        prepayRequest.setMchid(PropertiesUtil.getLocalProperty("mchId"));
+        prepayRequest.setNotifyUrl(PropertiesUtil.getLocalProperty("jsapiNotifyUrl"));
+        prepayRequest.setOutTradeNo(request.getOutTradeNo());
+        Payer payer = new Payer();
+        payer.setOpenid(request.getOpenId());
+        prepayRequest.setPayer(payer);
+        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(prepayRequest);
+        log.info("JSAPI下单:\n参数:{}\n结果:{}", JSONObject.toJSON(prepayRequest),
+                JSONObject.toJSON(response));
+        return response;
+    }
+
+    private String getAppIdByAppletType(AppletType appletType) {
+        if (null == appletType) {
+            return PropertiesUtil.getLocalProperty("appId");
+        }
+        return appletType == AppletType.HOSPITAL_SERVICE ?
+                PropertiesUtil.getLocalProperty("appletAppId") :
+                PropertiesUtil.getLocalProperty("appletMallAppId");
+    }
+
+    public Transaction queryOrderState(WechatPayGlobalRequest request) {
+        Config config = WxPayConfigUtil.getInstance().getConfig();
+        JsapiService service = new JsapiService.Builder().config(config).build();
+        QueryOrderByOutTradeNoRequest queryOrderRequest = new QueryOrderByOutTradeNoRequest();
+        queryOrderRequest.setOutTradeNo(request.getOutTradeNo());
+        queryOrderRequest.setMchid(PropertiesUtil.getLocalProperty("mchId"));
+        Transaction transaction = service.queryOrderByOutTradeNo(queryOrderRequest);
+        log.info("查询订单状态【{}】:{}", request.getOutTradeNo(), transaction);
+        return transaction;
+    }
+
+    public void closeOrder(WechatPayGlobalRequest request) {
+        Config config = WxPayConfigUtil.getInstance().getConfig();
+        JsapiService service = new JsapiService.Builder().config(config).build();
+        CloseOrderRequest closeOrderRequest = new CloseOrderRequest();
+        closeOrderRequest.setOutTradeNo(request.getOutTradeNo());
+        closeOrderRequest.setMchid(PropertiesUtil.getLocalProperty("mchId"));
+        service.closeOrder(closeOrderRequest);
+        log.info("关闭微信订单:{}", request.getOutTradeNo());
+    }
+
+    public NativePayResponse nativePrepay(WechatPayGlobalRequest request) {
+        Config config = WxPayConfigUtil.getInstance().getConfig();
+        NativePayService service = new NativePayService.Builder().config(config).build();
+        com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest prepayRequest
+                = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
+        com.wechat.pay.java.service.payments.nativepay.model.Amount amount
+                = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
+        amount.setTotal(request.getTotalAmount());
+        prepayRequest.setAmount(amount);
+        prepayRequest.setDescription(request.getDescription());
+        prepayRequest.setAppid(getAppIdByAppletType(request.getAppletType()));
+        prepayRequest.setMchid(PropertiesUtil.getLocalProperty("mchId"));
+        prepayRequest.setNotifyUrl(PropertiesUtil.getLocalProperty("nativeNotifyUrl"));
+        prepayRequest.setOutTradeNo(SnowFlakeId.instance().nextNativePayTradeNo());
+        com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse prepayResponse = service.prepay(prepayRequest);
+        log.info("获取微信支付二维码:\n参数:{}\n结果:{}", JSONObject.toJSON(prepayRequest), prepayResponse.getCodeUrl());
+        return new NativePayResponse(prepayResponse.getCodeUrl(), prepayRequest.getOutTradeNo());
+    }
+
+    public RefundResponse refund(WechatPayGlobalRequest request) {
+        Config config = WxPayConfigUtil.getInstance().getConfig();
+        RefundService service = new RefundService.Builder().config(config).build();
+        CreateRequest createRequest = new CreateRequest();
+        createRequest.setOutTradeNo(request.getOutTradeNo());
+        createRequest.setOutRefundNo(makeOutRefundNo(request.getOutTradeNo()));
+        AmountReq amountReq = new AmountReq();
+        amountReq.setRefund(Long.valueOf(request.getRefundAmount()));
+        amountReq.setTotal(Long.valueOf(request.getTotalAmount()));
+        amountReq.setCurrency("CNY");
+        createRequest.setAmount(amountReq);
+        RefundResponse response = new RefundResponse();
+        try {
+            Refund refund = service.create(createRequest);
+            log.info("微信支付退款:{}", refund);
+            response.setTradeState(Transaction.TradeStateEnum.REFUND);
+            response.setRefundId(refund.getRefundId());
+            return response;
+        } catch (Exception e) {
+            String msg = e.getMessage();
+            log.info("微信支付退款:{}", e.getMessage());
+            if (msg.contains("订单不存在")) {
+                response.setTradeState(Transaction.TradeStateEnum.NOTPAY);
+                response.setMessage("订单不存在");
+                return response;
+            }
+            if (msg.contains("订单已全额退款")) {
+                response.setTradeState(Transaction.TradeStateEnum.REFUND);
+                response.setMessage("订单已全额退款");
+                return response;
+            }
+            if (msg.contains("订单已关闭")) {
+                response.setTradeState(Transaction.TradeStateEnum.CLOSED);
+                response.setMessage("订单已关闭");
+                return response;
+            }
+            response.setTradeState(Transaction.TradeStateEnum.NOTPAY);
+            response.setMessage("未知的状态");
+            return response;
+        }
+    }
+
+    private String makeOutRefundNo(String tradeNo) {
+        String[] tempArr = tradeNo.split("_");
+        return "REFUND_" + tempArr[tempArr.length - 1];
+    }
+
+    public Transaction decryptNotify(WechatPayGlobalRequest request) {
+        HttpServletRequest httpServletRequest = request.getHttpServletRequest();
+        RequestParam requestParam = new RequestParam.Builder()
+                .serialNumber(httpServletRequest.getHeader("Wechatpay-Serial"))
+                .nonce(httpServletRequest.getHeader("Wechatpay-Nonce"))
+                .signature(httpServletRequest.getHeader("Wechatpay-Signature"))
+                .timestamp(httpServletRequest.getHeader("Wechatpay-Timestamp"))
+                .body(readHttpServletRequestBody(httpServletRequest))
+                .build();
+        RSAAutoCertificateConfig config = WxPayConfigUtil.getInstance().getConfig();
+        NotificationParser parser = new NotificationParser(config);
+        Transaction transaction = parser.parse(requestParam, Transaction.class);
+        log.info("微信回调SDK解密:{}", transaction);
+        return transaction;
+    }
+
+    private String readHttpServletRequestBody(HttpServletRequest httpServletRequest) {
+        StringBuilder requestBody = new StringBuilder();
+        String line;
+        try {
+            BufferedReader reader = httpServletRequest.getReader();
+            while ((line = reader.readLine()) != null) {
+                requestBody.append(line);
+            }
+        } catch (IOException e) {
+            log.error("微信回调解密出错,", e);
+        }
+        return requestBody.toString();
+    }
+}

+ 16 - 0
src/main/java/thyyxxk/wxservice_server/factory/wechatpay/model/NativePayResponse.java

@@ -0,0 +1,16 @@
+package thyyxxk.wxservice_server.factory.wechatpay.model;
+
+import lombok.Data;
+
+@Data
+public class NativePayResponse {
+    private String codeUrl;
+    private String tradeNo;
+
+    public NativePayResponse() {}
+
+    public NativePayResponse(String codeUrl, String tradeNo) {
+        this.codeUrl = codeUrl;
+        this.tradeNo = tradeNo;
+    }
+}

+ 82 - 0
src/main/java/thyyxxk/wxservice_server/factory/wechatpay/model/WechatPayGlobalRequest.java

@@ -0,0 +1,82 @@
+package thyyxxk.wxservice_server.factory.wechatpay.model;
+
+import lombok.Getter;
+import thyyxxk.wxservice_server.entity.wxapi.wxapplet.request.AppletType;
+
+import javax.servlet.http.HttpServletRequest;
+
+@Getter
+public class WechatPayGlobalRequest {
+    private AppletType appletType;
+    private String outTradeNo;
+    private String openId;
+    private String description;
+    private Integer totalAmount;
+    private Integer refundAmount;
+    private HttpServletRequest httpServletRequest;
+
+    private WechatPayGlobalRequest() {}
+
+    private WechatPayGlobalRequest(AppletType appletType, String outTradeNo, String openId,
+                                   String description, Integer totalAmount, Integer refundAmount,
+                                   HttpServletRequest httpServletRequest) {
+        this.appletType = appletType;
+        this.outTradeNo = outTradeNo;
+        this.openId = openId;
+        this.description = description;
+        this.totalAmount = totalAmount;
+        this.refundAmount = refundAmount;
+        this.httpServletRequest = httpServletRequest;
+    }
+
+    public static class Builder {
+        private AppletType appletType;
+        private String outTradeNo;
+        private String openId;
+        private String description;
+        private Integer totalAmount;
+        private Integer refundAmount;
+        private HttpServletRequest httpServletRequest;
+
+        public Builder appletType(AppletType appletType) {
+            this.appletType = appletType;
+            return this;
+        }
+
+        public Builder outTradeNo(String outTradeNo) {
+            this.outTradeNo = outTradeNo;
+            return this;
+        }
+
+        public Builder openId(String openId) {
+            this.openId = openId;
+            return this;
+        }
+
+        public Builder description(String description) {
+            this.description = description;
+            return this;
+        }
+
+        public Builder totalAmount(Integer totalAmount) {
+            this.totalAmount = totalAmount;
+            return this;
+        }
+
+        public Builder refundAmount(Integer refundAmount) {
+            this.refundAmount = refundAmount;
+            return this;
+        }
+
+        public Builder httpServletRequest(HttpServletRequest httpServletRequest) {
+            this.httpServletRequest = httpServletRequest;
+            return this;
+        }
+
+        public WechatPayGlobalRequest build() {
+            return new WechatPayGlobalRequest(appletType, outTradeNo, openId, description,
+                    totalAmount, refundAmount, httpServletRequest);
+        }
+    }
+
+}

+ 19 - 10
src/main/java/thyyxxk/wxservice_server/service/SaveAppletPayResultService.java

@@ -22,7 +22,9 @@ import thyyxxk.wxservice_server.entity.inpatient.GetZyFeeParam;
 import thyyxxk.wxservice_server.entity.wxapi.wxapplet.response.WxAppletOrder;
 import thyyxxk.wxservice_server.utils.*;
 
+import java.util.ArrayList;
 import java.util.Date;
+import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -232,15 +234,10 @@ public class SaveAppletPayResultService {
         String url = hrgApiUrl + "/saveTcPrescription";
         JSONObject params = new JSONObject();
         params.put("patientId", order.getPatientId());
-        JSONArray templateIds = new JSONArray();
-        String[] splitArr = order.getCartIds().split(",");
-        if (splitArr.length > 1) {
-            for (int i = 1; i < splitArr.length; i ++) {
-                String temp = splitArr[i];
-                if (StringUtil.notBlank(temp)) {
-                    templateIds.add(Integer.parseInt(temp));
-                }
-            }
+        List<Integer> templateIds = new ArrayList<>();
+        String[] cartIdArray = order.getCartIds().split(",");
+        if (cartIdArray.length > 1) {
+            templateIds = appletDao.selectTemplateIdsByCartIdArray(cartIdArray);
         }
         params.put("templateIds", templateIds);
         params.put("psOrdNum", order.getTradeNo());
@@ -255,8 +252,20 @@ public class SaveAppletPayResultService {
             return ResultVoUtil.fail(ExceptionEnum.NETWORK_ERROR);
         }
         if (null == response.getCode() || 0 != response.getCode()) {
-            return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, response.getMessage());
+            if (null != response.getMessage() && response.getMessage().contains("已经缴费成功")) {
+                appletDao.updateSuccessHisStatus(order.getTradeNo());
+                return ResultVoUtil.success("保存套餐信息成功。");
+            }
+            log.info("【订单号:{}】发起自动退款:{}", order.getTradeNo(), response.getMessage());
+            ResultVo<WxAppletOrder> refund = refundService.wxAppletRefund(order);
+            log.info("【订单号:{}】自动退款结果:{}", order.getTradeNo(), refund.getCode());
+            if (refund.getCode() == ExceptionEnum.SUCCESS.getCode()) {
+                appletDao.refundOrder(order.getTradeNo(), response.getMessage());
+                return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, "【" + response.getMessage() +  "】已为您自动退款,请留意到账信息。");
+            }
+            return ResultVoUtil.fail(ExceptionEnum.INTERNAL_SERVER_ERROR, "【" + response.getMessage() +  "】自动退款失败,请联系服务中心进行退款。");
         }
+        appletDao.updateSuccessHisStatus(order.getTradeNo());
         return ResultVoUtil.success("保存套餐信息成功。");
     }
 

+ 47 - 101
src/main/java/thyyxxk/wxservice_server/service/WxApiService.java

@@ -1,13 +1,9 @@
 package thyyxxk.wxservice_server.service;
 
 import com.alibaba.fastjson.JSONObject;
-import com.wechat.pay.java.core.Config;
 import com.wechat.pay.java.core.util.GsonUtil;
-import com.wechat.pay.java.service.payments.jsapi.JsapiService;
-import com.wechat.pay.java.service.payments.jsapi.JsapiServiceExtension;
 import com.wechat.pay.java.service.payments.jsapi.model.*;
 import com.wechat.pay.java.service.payments.model.Transaction;
-import com.wechat.pay.java.service.payments.nativepay.NativePayService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -16,13 +12,14 @@ import thyyxxk.wxservice_server.constant.OrderType;
 import thyyxxk.wxservice_server.dao.WxApiDao;
 import thyyxxk.wxservice_server.entity.ResultVo;
 import thyyxxk.wxservice_server.entity.appointment.DoctorInfo;
-import thyyxxk.wxservice_server.entity.appointment.WeChatPayParam;
 import thyyxxk.wxservice_server.entity.wxapi.JsApiSHA1;
 import thyyxxk.wxservice_server.entity.wxapi.GenMzPayQrcodeParam;
 import thyyxxk.wxservice_server.entity.wxapi.WxPayOrder;
 import thyyxxk.wxservice_server.entity.wxapi.WxPyQrcdPrm;
+import thyyxxk.wxservice_server.factory.wechatpay.WeChatPayService;
+import thyyxxk.wxservice_server.factory.wechatpay.model.NativePayResponse;
+import thyyxxk.wxservice_server.factory.wechatpay.model.WechatPayGlobalRequest;
 import thyyxxk.wxservice_server.utils.*;
-import thyyxxk.wxservice_server.utils.wxpay.WxPayConfigUtil;
 
 import java.util.*;
 import java.util.concurrent.TimeUnit;
@@ -54,13 +51,13 @@ public class WxApiService {
         return ResultVoUtil.success(data);
     }
 
-    public ResultVo<WxPayOrder> createPayOrder(WeChatPayParam param) {
+    public ResultVo<WxPayOrder> createPayOrder(WxPayOrder order) {
         WxPayOrder existOrder = null;
-        if (param.getOrderType() == OrderType.CLINIC_REGISTER.getCode() ||
-                param.getOrderType() == OrderType.REGISTRATION.getCode()) {
-            existOrder = dao.selectSameGhOrder(param.getPatientId(), param.getMzyRequestId());
-        } else if (param.getOrderType() == OrderType.OUTPATIENT.getCode()) {
-            existOrder = dao.selectSameMzPayOrder(param.getHisOrdNum(), param.getTotalFee().doubleValue());
+        if (order.getOrderType() == OrderType.CLINIC_REGISTER.getCode() ||
+                order.getOrderType() == OrderType.REGISTRATION.getCode()) {
+            existOrder = dao.selectSameGhOrder(order.getPatientId(), order.getMzyRequestId());
+        } else if (order.getOrderType() == OrderType.OUTPATIENT.getCode()) {
+            existOrder = dao.selectSameMzPayOrder(order.getHisOrdNum(), order.getTotalFee().doubleValue());
         }
         if (null != existOrder) {
             if (existOrder.getTradeState() == Transaction.TradeStateEnum.SUCCESS) {
@@ -73,79 +70,41 @@ public class WxApiService {
                         return ResultVoUtil.success(existOrder);
                     }
                 }
-                if (null == param.getYjReqNo()) {
-                    param.setYjReqNo(existOrder.getYjReqNo());
+                if (null == order.getYjReqNo()) {
+                    order.setYjReqNo(existOrder.getYjReqNo());
                 }
             }
         }
 
-        String appId = PropertiesUtil.getLocalProperty("appId");
-        String merchantId = PropertiesUtil.getLocalProperty("mchId");
-        String tradeNo = SnowFlakeId.instance().nextId();
-        int totalFee = DecimalTool.moneyYuanToFen(param.getTotalFee()).intValue();
-        String notifyUrl = "http://staticweb.hnthyy.cn/wxserver/wxPayNotify/jsapi";
-        Config config = WxPayConfigUtil.getInstance().getConfig();
-        JsapiServiceExtension service = new JsapiServiceExtension .Builder().config(config).build();
-        PrepayRequest request = new PrepayRequest();
-        Amount amount = new Amount();
-        amount.setTotal(totalFee);
-        request.setAmount(amount);
-        request.setDescription(param.getBody());
-        request.setAppid(appId);
-        request.setMchid(merchantId);
-        request.setNotifyUrl(notifyUrl);
-        request.setOutTradeNo(tradeNo);
-        Payer payer = new Payer();
-        payer.setOpenid(param.getOpenId());
-        request.setPayer(payer);
-        PrepayWithRequestPaymentResponse response = service.prepayWithRequestPayment(request);
-
-        WxPayOrder order = new WxPayOrder();
-        order.setBody(param.getBody());
-        order.setOrderType(param.getOrderType());
-        order.setOpenId(param.getOpenId());
-        order.setTotalFee(param.getTotalFee());
-        order.setPatientId(param.getPatientId());
-        order.setPatientName(dao.selectPatientName(param.getPatientId()));
-        order.setAppId(appId);
-        order.setMchId(merchantId);
+        int totalAmt = DecimalTool.moneyYuanToFen(order.getTotalFee()).intValue();
+        order.setTradeNo(SnowFlakeId.instance().nextId());
+        order.setMchId(PropertiesUtil.getLocalProperty("mchId"));
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .appletType(null).outTradeNo(order.getTradeNo())
+                .openId(order.getOpenId()).description(order.getBody())
+                .totalAmount(totalAmt).build();
+        PrepayWithRequestPaymentResponse response = new WeChatPayService().jsApiPrepay(request);
+        order.setPatientName(dao.selectPatientName(order.getPatientId()));
+        order.setAppId(response.getAppId());
         order.setPrepayId(response.getPackageVal());
         order.setTimeStamp(response.getTimeStamp());
         order.setSerialNo(response.getNonceStr());
         order.setSignType(response.getSignType());
         order.setPaySign(response.getPaySign());
-        order.setTradeNo(tradeNo);
-        order.setSpbillCreateIp(param.getClientIp());
         order.setCreateDatetime(new Date());
         order.setTradeState(Transaction.TradeStateEnum.NOTPAY);
-        order.setHisOrdNum(param.getHisOrdNum());
-        order.setMzyRequestId(param.getMzyRequestId());
-        order.setYjReqNo(param.getYjReqNo());
-        order.setInpatientNo(param.getInpatientNo());
-        order.setAdmissTimes(param.getAdmissTimes());
-        order.setApTime(param.getApTime());
         dao.insertNewOrder(order);
-        log.info("统一下单成功:{}", order);
         return ResultVoUtil.success(order);
     }
 
     public ResultVo<JSONObject> queryOrderStateOnly(String tradeNo) {
-        Transaction transaction = queryOrderTradeState(tradeNo);
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .outTradeNo(tradeNo).build();
+        Transaction transaction = new WeChatPayService().queryOrderState(request);
         JSONObject response = JSONObject.parseObject(GsonUtil.toJson(transaction));
         return ResultVoUtil.success(response);
     }
 
-    private Transaction queryOrderTradeState(String tradeNo) {
-        Config config = WxPayConfigUtil.getInstance().getConfig();
-        JsapiService service = new JsapiService.Builder().config(config).build();
-        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
-        request.setOutTradeNo(tradeNo);
-        request.setMchid(PropertiesUtil.getLocalProperty("mchId"));
-        Transaction transaction = service.queryOrderByOutTradeNo(request);
-        log.info("查询状态:{}", transaction);
-        return transaction;
-    }
-
     public ResultVo<Object> queryOrderState(String tradeNo) {
         try {
             while (TradeVectorUtil.tradeNoBeingQuery(tradeNo) || TradeVectorUtil.tradeNoBeingRefund(tradeNo)) {
@@ -170,7 +129,11 @@ public class WxApiService {
                 log.info("订单号:{} 的门诊缴费信息已保存,无需再次查询订单状态。", order.getTradeNo());
                 return ResultVoUtil.success("保存门诊缴费信息成功。");
             }
-            Transaction transaction = queryOrderTradeState(tradeNo);
+
+            WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                    .outTradeNo(tradeNo).build();
+            Transaction transaction = new WeChatPayService().queryOrderState(request);
+
             Transaction.TradeStateEnum tradeState = transaction.getTradeState();
             if (tradeState == Transaction.TradeStateEnum.SUCCESS) {
                 String successTime = transaction.getSuccessTime()
@@ -203,7 +166,9 @@ public class WxApiService {
     }
 
     public ResultVo<String> generateMzGuideBillPayQrcode(GenMzPayQrcodeParam param) {
-        String[] nativePays = getWxNativePayUrl(param.getTotalAmt(), "湖南泰和医院-门诊缴费");
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .totalAmount(param.getTotalAmt()).description("湖南泰和医院-门诊缴费").build();
+        NativePayResponse response = new WeChatPayService().nativePrepay(request);
         long timesStamp = System.currentTimeMillis() / 1000;
         WxPayOrder order = new WxPayOrder();
         order.setAppId(PropertiesUtil.getLocalProperty("appId"));
@@ -214,14 +179,14 @@ public class WxApiService {
         order.setPatientName(dao.selectPatientName(param.getPatientId()));
         order.setMchId(PropertiesUtil.getLocalProperty("mchId"));
         order.setTimeStamp(String.valueOf(timesStamp));
-        order.setTradeNo(nativePays[1]);
+        order.setTradeNo(response.getTradeNo());
         order.setCreateDatetime(new Date());
         order.setTradeState(Transaction.TradeStateEnum.NOTPAY);
         order.setSerialNo(SnowFlakeId.instance().nextId());
         order.setOrderType(OrderType.OUTPATIENT.getCode());
         order.setHisOrdNum(param.getHisOrdNum());
         dao.insertNewOrder(order);
-        return ResultVoUtil.success(nativePays[0]);
+        return ResultVoUtil.success(response.getCodeUrl());
     }
 
     public ResultVo<Map<String, String>> getWxPayQrcode(WxPyQrcdPrm param) {
@@ -240,7 +205,11 @@ public class WxApiService {
             order.setInpatientNo(param.getInpatientNo());
             order.setAdmissTimes(param.getAdmissTimes());
         }
-        String[] nativePays = getWxNativePayUrl(param.getTotalAmt(), param.getDescription());
+
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .totalAmount(param.getTotalAmt()).description(param.getDescription()).build();
+        NativePayResponse response = new WeChatPayService().nativePrepay(request);
+
         long timesStamp = System.currentTimeMillis() / 1000;
         String orderTypeName = OrderType.get(param.getOrderType()).getLabel();
         order.setAppId(PropertiesUtil.getLocalProperty("appId"));
@@ -251,15 +220,15 @@ public class WxApiService {
         order.setPatientName(patName);
         order.setMchId(PropertiesUtil.getLocalProperty("mchId"));
         order.setTimeStamp(String.valueOf(timesStamp));
-        order.setTradeNo(nativePays[1]);
+        order.setTradeNo(response.getTradeNo());
         order.setCreateDatetime(new Date());
         order.setTradeState(Transaction.TradeStateEnum.NOTPAY);
         order.setSerialNo(SnowFlakeId.instance().nextId());
         order.setOrderType(param.getOrderType());
         dao.insertNewOrder(order);
         Map<String, String> map = new HashMap<>();
-        map.put("qrcodeUrl", nativePays[0]);
-        map.put("tradeNo", nativePays[1]);
+        map.put("qrcodeUrl", response.getCodeUrl());
+        map.put("tradeNo", response.getTradeNo());
         map.put("serialNo", order.getSerialNo());
         return ResultVoUtil.success(map);
     }
@@ -275,21 +244,15 @@ public class WxApiService {
         if (tradeState == Transaction.TradeStateEnum.SUCCESS) {
             return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR,"订单已支付,无法关闭。");
         }
-        executeCloseOrder(order.getTradeNo());
+
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .outTradeNo(order.getTradeNo()).build();
+        new WeChatPayService().closeOrder(request);
+
         dao.updatePayStatusOnly(order.getTradeNo(), Transaction.TradeStateEnum.CLOSED);
         return ResultVoUtil.success("关闭订单成功。");
     }
 
-    public void executeCloseOrder(String tradeNo) {
-        Config config = WxPayConfigUtil.getInstance().getConfig();
-        JsapiService service = new JsapiService.Builder().config(config).build();
-        CloseOrderRequest request = new CloseOrderRequest();
-        request.setOutTradeNo(tradeNo);
-        request.setMchid(PropertiesUtil.getLocalProperty("mchId"));
-        service.closeOrder(request);
-        log.info("关闭微信订单:{}", tradeNo);
-    }
-
     public ResultVo<DoctorInfo> getDoctorInfo(String doctorCode) {
         DoctorInfo doctorInfo = dao.selectDoctorInfo(doctorCode);
         if (null == doctorInfo) {
@@ -309,21 +272,4 @@ public class WxApiService {
         }
         return savePayResultService.saveZyYjjInfo(order);
     }
-
-    private String[] getWxNativePayUrl(int payAmt, String description) {
-        Config config = WxPayConfigUtil.getInstance().getConfig();
-        NativePayService service = new NativePayService.Builder().config(config).build();
-        com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest request = new com.wechat.pay.java.service.payments.nativepay.model.PrepayRequest();
-        com.wechat.pay.java.service.payments.nativepay.model.Amount amount = new com.wechat.pay.java.service.payments.nativepay.model.Amount();
-        amount.setTotal(payAmt);
-        request.setAmount(amount);
-        request.setDescription(description);
-        request.setAppid(PropertiesUtil.getLocalProperty("appId"));
-        request.setMchid(PropertiesUtil.getLocalProperty("mchId"));
-        request.setNotifyUrl(PropertiesUtil.getLocalProperty("nativeNotifyUrl"));
-        request.setOutTradeNo(SnowFlakeId.instance().nextNativePayTradeNo());
-        com.wechat.pay.java.service.payments.nativepay.model.PrepayResponse response = service.prepay(request);
-        log.info("获取微信支付二维码:\n参数:{}\n结果:{}", JSONObject.toJSON(request), response.getCodeUrl());
-        return new String[] {response.getCodeUrl(), request.getOutTradeNo()};
-    }
 }

+ 6 - 34
src/main/java/thyyxxk/wxservice_server/service/WxPayNotifyService.java

@@ -1,8 +1,5 @@
 package thyyxxk.wxservice_server.service;
 
-import com.wechat.pay.java.core.RSAAutoCertificateConfig;
-import com.wechat.pay.java.core.notification.NotificationParser;
-import com.wechat.pay.java.core.notification.RequestParam;
 import com.wechat.pay.java.service.payments.model.Transaction;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -10,11 +7,11 @@ import org.springframework.stereotype.Service;
 import thyyxxk.wxservice_server.constant.OrderType;
 import thyyxxk.wxservice_server.dao.WxApiDao;
 import thyyxxk.wxservice_server.entity.wxapi.WxPayOrder;
+import thyyxxk.wxservice_server.factory.wechatpay.WeChatPayService;
+import thyyxxk.wxservice_server.factory.wechatpay.model.WechatPayGlobalRequest;
 import thyyxxk.wxservice_server.utils.TradeVectorUtil;
-import thyyxxk.wxservice_server.utils.wxpay.WxPayConfigUtil;
 
 import javax.servlet.http.HttpServletRequest;
-import java.io.BufferedReader;
 
 /**
  * @author dj
@@ -31,8 +28,10 @@ public class WxPayNotifyService {
         this.savePayResultService = savePayResultService;
     }
 
-    public void nativeNotify(HttpServletRequest request) throws Exception {
-        Transaction transaction = decryptNotifyBody(request);
+    public void nativeNotify(HttpServletRequest httpServletRequest) throws Exception {
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .httpServletRequest(httpServletRequest).build();
+        Transaction transaction = new WeChatPayService().decryptNotify(request);
         String tradeNo = transaction.getOutTradeNo();
         WxPayOrder order = dao.selectOrderByTradeNo(tradeNo);
         Transaction.TradeStateEnum tradeState = order.getTradeState();
@@ -65,31 +64,4 @@ public class WxPayNotifyService {
                 break;
         }
     }
-
-    public void jsapiNotify(HttpServletRequest request) throws Exception {
-        decryptNotifyBody(request);
-    }
-
-    private Transaction decryptNotifyBody(HttpServletRequest request) throws Exception {
-        BufferedReader reader = request.getReader();
-        StringBuilder requestBody = new StringBuilder();
-        String line;
-        while ((line = reader.readLine()) != null) {
-            requestBody.append(line);
-        }
-        RequestParam requestParam = new RequestParam.Builder()
-                .serialNumber(request.getHeader("Wechatpay-Serial"))
-                .nonce(request.getHeader("Wechatpay-Nonce"))
-                .signature(request.getHeader("Wechatpay-Signature"))
-                .timestamp(request.getHeader("Wechatpay-Timestamp"))
-                .body(requestBody.toString())
-                .build();
-
-        log.info("微信回调SDK解密开始:{}", requestParam);
-        RSAAutoCertificateConfig config = WxPayConfigUtil.getInstance().getConfig();
-        NotificationParser parser = new NotificationParser(config);
-        Transaction transaction = parser.parse(requestParam, Transaction.class);
-        log.info("微信回调SDK解密结束:{}", transaction);
-        return transaction;
-    }
 }

+ 14 - 51
src/main/java/thyyxxk/wxservice_server/service/WxRefundService.java

@@ -1,11 +1,6 @@
 package thyyxxk.wxservice_server.service;
 
-import com.wechat.pay.java.core.Config;
 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 lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -16,6 +11,8 @@ import thyyxxk.wxservice_server.entity.wxapi.RefundResponse;
 import thyyxxk.wxservice_server.entity.wxapi.RfndPrm;
 import thyyxxk.wxservice_server.entity.wxapi.WxPayOrder;
 import thyyxxk.wxservice_server.entity.wxapi.wxapplet.response.WxAppletOrder;
+import thyyxxk.wxservice_server.factory.wechatpay.WeChatPayService;
+import thyyxxk.wxservice_server.factory.wechatpay.model.WechatPayGlobalRequest;
 import thyyxxk.wxservice_server.utils.*;
 import thyyxxk.wxservice_server.utils.wxpay.WxPayConfigUtil;
 
@@ -79,7 +76,12 @@ public class WxRefundService {
 
     public ResultVo<String> startRefund(WxPayOrder order) {
         int refundAmount = DecimalTool.moneyYuanToFen(order.getTotalFee()).intValue();
-        RefundResponse response = executeRefund(order.getTradeNo(), refundAmount, refundAmount);
+
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .outTradeNo(order.getTradeNo()).refundAmount(refundAmount)
+                .totalAmount(refundAmount).build();
+        RefundResponse response = new WeChatPayService().refund(request);
+
         if (response.getTradeState() == Transaction.TradeStateEnum.REFUND) {
             TradeVectorUtil.addRefunded(order.getTradeNo());
             String refundId = response.getRefundId();
@@ -97,8 +99,12 @@ public class WxRefundService {
     }
 
     public ResultVo<WxAppletOrder> wxAppletRefund(WxAppletOrder order) {
-        RefundResponse response = executeRefund(order.getTradeNo(),
-                order.getRefundAmount(), order.getTotalAmount());
+
+        WechatPayGlobalRequest request = new WechatPayGlobalRequest.Builder()
+                .outTradeNo(order.getTradeNo()).refundAmount(order.getRefundAmount())
+                .totalAmount(order.getTotalAmount()).build();
+        RefundResponse response = new WeChatPayService().refund(request);
+
         if (response.getTradeState() == Transaction.TradeStateEnum.REFUND) {
             if (StringUtil.notBlank(response.getMessage())) {
                 if ("订单已全额退款".equals(response.getMessage())) {
@@ -112,47 +118,4 @@ public class WxRefundService {
         }
         return ResultVoUtil.fail(ExceptionEnum.LOGICAL_ERROR, response.getMessage());
     }
-
-    public RefundResponse executeRefund(String tradeNo, long refundAmt, long totalAmt) {
-        Config config = WxPayConfigUtil.getInstance().getConfig();
-        RefundService service = new RefundService.Builder().config(config).build();
-        CreateRequest request = new CreateRequest();
-        request.setOutTradeNo(tradeNo);
-        request.setOutRefundNo(SnowFlakeId.instance().nextId());
-        AmountReq amountReq = new AmountReq();
-        amountReq.setRefund(refundAmt);
-        amountReq.setTotal(totalAmt);
-        amountReq.setCurrency("CNY");
-        request.setAmount(amountReq);
-        RefundResponse response = new RefundResponse();
-        try {
-            Refund refund = service.create(request);
-            log.info("微信支付退款:{}", refund);
-            response.setTradeState(Transaction.TradeStateEnum.REFUND);
-            response.setRefundId(refund.getRefundId());
-            return response;
-        } catch (Exception e) {
-            String msg = e.getMessage();
-            log.info("微信支付退款:{}", e.getMessage());
-            if (msg.contains("订单不存在")) {
-                response.setTradeState(Transaction.TradeStateEnum.NOTPAY);
-                response.setMessage("订单不存在");
-                return response;
-            }
-            if (msg.contains("订单已全额退款")) {
-                response.setTradeState(Transaction.TradeStateEnum.REFUND);
-                response.setMessage("订单已全额退款");
-                return response;
-            }
-            if (msg.contains("订单已关闭")) {
-                response.setTradeState(Transaction.TradeStateEnum.CLOSED);
-                response.setMessage("订单已关闭");
-                return response;
-            }
-            response.setTradeState(Transaction.TradeStateEnum.NOTPAY);
-            response.setMessage("未知的状态");
-            return response;
-        }
-    }
-
 }

+ 4 - 4
src/main/resources/application.yml

@@ -32,11 +32,11 @@ mybatis:
   configuration:
     map-underscore-to-camel-case: true
 
-#hrgApiUrl: http://172.16.30.119:8089/thmz/api/v1
-#appletThmzUrl: http://172.16.30.119:8089/thmz
+hrgApiUrl: http://172.16.30.119:8089/thmz/api/v1
+appletThmzUrl: http://172.16.30.119:8089/thmz
 
-hrgApiUrl: http://172.16.30.26:8089/thmz/api/v1
-appletThmzUrl: http://172.16.30.26:8089/thmz
+#hrgApiUrl: http://172.16.30.26:8089/thmz/api/v1
+#appletThmzUrl: http://172.16.30.26:8089/thmz
 
 inspectionUrl: http://172.16.32.178:622/pushservice.asmx?wsdl
 physicalCheck: http://172.16.32.183:8888/bdp/dataservice/api/