Commit d8d5c6623d4f8c10898c131d1076228ab7459b57

Authored by 陈威
1 parent a513b763
Exists in dev

微信支付

backend/lpg-user/pom.xml
... ... @@ -67,6 +67,37 @@
67 67 <version>${parent.version}</version>
68 68 </dependency>
69 69  
  70 + <!--weixin-java-pay-->
  71 + <dependency>
  72 + <groupId>com.github.binarywang</groupId>
  73 + <artifactId>weixin-java-pay</artifactId>
  74 + <version>4.1.0</version>
  75 + </dependency>
  76 + <!--weixin-java-common-->
  77 + <dependency>
  78 + <groupId>com.github.binarywang</groupId>
  79 + <artifactId>weixin-java-common</artifactId>
  80 + <version>4.1.0</version>
  81 + </dependency>
  82 + <!--weixin-java-miniapp-->
  83 + <dependency>
  84 + <groupId>com.github.binarywang</groupId>
  85 + <artifactId>weixin-java-miniapp</artifactId>
  86 + <version>4.1.0</version>
  87 + </dependency>
  88 + <!--weixin-java-mp-->
  89 + <dependency>
  90 + <groupId>com.github.binarywang</groupId>
  91 + <artifactId>weixin-java-mp</artifactId>
  92 + <version>4.1.0</version>
  93 + </dependency>
  94 + <!--weixin-java-open-->
  95 + <dependency>
  96 + <groupId>com.github.binarywang</groupId>
  97 + <artifactId>weixin-java-open</artifactId>
  98 + <version>4.1.0</version>
  99 + </dependency>
  100 +
70 101 </dependencies>
71 102 <build>
72 103 <plugins>
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/controller/PaymentController.java 0 → 100644
... ... @@ -0,0 +1,41 @@
  1 +package com.hotent.lpg.user.controller;
  2 +
  3 +import com.hotent.lpg.user.enums.PayTypeEnum;
  4 +import com.hotent.lpg.user.manager.PaymentManage;
  5 +import com.hotent.lpg.user.vo.ResultData;
  6 +import lombok.AllArgsConstructor;
  7 +import lombok.extern.slf4j.Slf4j;
  8 +import org.springframework.validation.annotation.Validated;
  9 +import org.springframework.web.bind.annotation.*;
  10 +
  11 +@RestController
  12 +@RequestMapping("/payment/v1/")
  13 +@AllArgsConstructor
  14 +@Validated
  15 +@Slf4j
  16 +public class PaymentController {
  17 + private final PaymentManage paymentManage;
  18 +
  19 + /**
  20 + * 预支付
  21 + * @param ddid
  22 + * @return
  23 + */
  24 + @PostMapping("/{ddid}")
  25 + public ResultData pay(@PathVariable("ddid") String ddid) {
  26 + String payType = PayTypeEnum.WX.getName(); // 默认微信
  27 + return paymentManage.pay(ddid, payType);
  28 + }
  29 +
  30 + /**
  31 + * 支付回调
  32 + * @return
  33 + */
  34 + @PostMapping("/notify-order")
  35 + public String notifyOrder(@RequestBody String xmlData) {
  36 + log.warn("支付回调:{}", xmlData);
  37 + String res = paymentManage.notifyOrder(xmlData);
  38 + log.warn("处理状态:{}", res);
  39 + return res;
  40 + }
  41 +}
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/enums/PayTypeEnum.java 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +package com.hotent.lpg.user.enums;
  2 +import lombok.AllArgsConstructor;
  3 +import lombok.Getter;
  4 +
  5 +@Getter
  6 +@AllArgsConstructor
  7 +public enum PayTypeEnum {
  8 + WX("微信");
  9 +
  10 + private String name;
  11 +}
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/enums/TradeTypeEnum.java 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +package com.hotent.lpg.user.enums;
  2 +
  3 +import lombok.AllArgsConstructor;
  4 +import lombok.Getter;
  5 +
  6 +@Getter
  7 +@AllArgsConstructor
  8 +public enum TradeTypeEnum {
  9 + APP("APP"),
  10 + NATIVE("NATIVE"),
  11 + JSAPI("JSAPI"),
  12 + MWEB("MWEB");
  13 +
  14 + private String code;
  15 +}
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/PaymentManage.java 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +package com.hotent.lpg.user.manager;
  2 +
  3 +
  4 +import com.hotent.lpg.user.vo.ResultData;
  5 +
  6 +public interface PaymentManage {
  7 + ResultData pay(String ddid, String payType);
  8 +
  9 + String notifyOrder(String xmlData);
  10 +}
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/manager/impl/PaymentManageImpl.java 0 → 100644
... ... @@ -0,0 +1,138 @@
  1 +package com.hotent.lpg.user.manager.impl;
  2 +
  3 +import cn.hutool.core.util.RandomUtil;
  4 +import cn.hutool.core.util.StrUtil;
  5 +import com.alibaba.fastjson.JSONObject;
  6 +import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
  7 +import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
  8 +import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
  9 +import com.github.binarywang.wxpay.exception.WxPayException;
  10 +import com.github.binarywang.wxpay.service.WxPayService;
  11 +
  12 +import com.hotent.base.util.BeanUtils;
  13 +import com.hotent.lpg.common.model.WDd;
  14 +import com.hotent.lpg.user.dao.DdDao;
  15 +import com.hotent.lpg.user.enums.PayTypeEnum;
  16 +import com.hotent.lpg.user.manager.PaymentManage;
  17 +import com.hotent.lpg.user.util.LocalDateTimeUtils;
  18 +import com.hotent.lpg.user.util.WxPayConfiguration;
  19 +import com.hotent.lpg.user.vo.ResultData;
  20 +import lombok.AllArgsConstructor;
  21 +import lombok.extern.slf4j.Slf4j;
  22 +import org.springframework.stereotype.Service;
  23 +import org.springframework.transaction.annotation.Transactional;
  24 +
  25 +import java.math.BigDecimal;
  26 +import java.time.LocalDateTime;
  27 +
  28 +@Service
  29 +@Transactional
  30 +@AllArgsConstructor
  31 +@Slf4j
  32 +public class PaymentManageImpl implements PaymentManage {
  33 + private final DdDao ddDao;
  34 +
  35 + @Override
  36 + public ResultData pay(String ddid, String payType) {
  37 +
  38 + WDd wDd = ddDao.selectById(ddid);
  39 + if (BeanUtils.isEmpty(wDd)) {
  40 + return ResultData.error("订单不存在");
  41 + }
  42 + if (payType.equals(PayTypeEnum.WX.getName())) {
  43 + wDd.setFZffs(PayTypeEnum.WX.getName());
  44 + return wxPay(wDd);
  45 + }
  46 + return ResultData.error("支付方式错误");
  47 + }
  48 +
  49 +
  50 + private ResultData wxPay(WDd wDd) {
  51 + try {
  52 + String tradeType = wDd.getFZffs();
  53 + if (StrUtil.isBlank(tradeType)) {
  54 + return ResultData.error("支付方式错误");
  55 + }
  56 +
  57 + // 防止重新启动支付时报“商户订单号重复”,前面增加8位随机数,product_id最大32位
  58 + String outTradeNo = RandomUtil.randomString(8) + "_" + wDd.getId();
  59 + String body = wDd.getFDddh();
  60 + body = body.length() > 40 ? body.substring(0,39) : body;
  61 +
  62 + WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = new WxPayUnifiedOrderRequest();
  63 + wxPayUnifiedOrderRequest.setAppid(WxPayConfiguration.appId);
  64 + wxPayUnifiedOrderRequest.setOpenid(null);
  65 + wxPayUnifiedOrderRequest.setBody(body);
  66 + wxPayUnifiedOrderRequest.setOutTradeNo(outTradeNo);
  67 + wxPayUnifiedOrderRequest.setTotalFee(wDd.getFDdje().multiply(new BigDecimal(100)).intValue());
  68 + wxPayUnifiedOrderRequest.setTradeType(tradeType);
  69 +
  70 + JSONObject scene_info = new JSONObject();
  71 + scene_info.put("id", "LPG");
  72 + scene_info.put("name", "燃气");
  73 + wxPayUnifiedOrderRequest.setSceneInfo(scene_info.toString());
  74 + wxPayUnifiedOrderRequest.setNotifyUrl("https://zaoyin.peony.cn/server/hzys/payment/v1/notify-order"); // 支付回调地址,开放不用登录
  75 + wxPayUnifiedOrderRequest.setSpbillCreateIp("127.0.0.1");
  76 +
  77 + // trade_type=APP时
  78 + if("APP".equals(wxPayUnifiedOrderRequest.getTradeType())){
  79 +
  80 + }
  81 + // trade_type=NATIVE时
  82 + if("NATIVE".equals(wxPayUnifiedOrderRequest.getTradeType())){
  83 + wxPayUnifiedOrderRequest.setProductId(wxPayUnifiedOrderRequest.getOutTradeNo());
  84 + }
  85 + if ("JSAPI".equals(wxPayUnifiedOrderRequest.getTradeType())) {
  86 +
  87 + }
  88 + if ("MWEB".equals(wxPayUnifiedOrderRequest.getTradeType())) {
  89 +
  90 + }
  91 + WxPayService wxPayService = WxPayConfiguration.getPayService();
  92 + ddDao.updateById(wDd);
  93 + return ResultData.success(wxPayService.createOrder(wxPayUnifiedOrderRequest));
  94 + } catch (WxPayException e) {
  95 + if("INVALID_REQUEST".equals(e.getErrCode())){
  96 + return ResultData.error("订单号重复,请重新下单");
  97 + }
  98 + e.printStackTrace();
  99 + return ResultData.error(e.getReturnMsg() + "" + e.getCustomErrorMsg() + "" + e.getErrCodeDes());
  100 + }
  101 + }
  102 +
  103 +
  104 + @Override
  105 + public String notifyOrder(String xmlData) {
  106 + WxPayService wxPayService = WxPayConfiguration.getPayService();
  107 + try {
  108 + WxPayOrderNotifyResult notifyResult = wxPayService.parseOrderNotifyResult(xmlData);
  109 + String ddid = notifyResult.getOutTradeNo().split("_")[1];
  110 + WDd wDd = ddDao.selectById(ddid);
  111 + if (null == wDd) {
  112 + return WxPayNotifyResponse.fail("订单不存在");
  113 + }
  114 + BigDecimal payPrice = wDd.getFDdje();
  115 + if (payPrice.multiply(new BigDecimal(100)).intValue() != notifyResult.getTotalFee()) {
  116 + return WxPayNotifyResponse.fail("付款金额与订单金额不等");
  117 + }
  118 +
  119 + String timeEnd = notifyResult.getTimeEnd();
  120 + LocalDateTime paymentTime = LocalDateTimeUtils.parse(timeEnd);
  121 +// wDdb.setfFksj(paymentTime);
  122 +// wDdb.setfZfdh(notifyResult.getTransactionId());
  123 +// wDdb.setfSffk("是");
  124 +// wDdb.setfDdzt("已付款");
  125 +// wDdb.setfPtddzt("待审批");
  126 +// wDdbDao.updateById(wDdb);
  127 +//
  128 +// if (StrUtil.isNotBlank(wDdb.getfZpid())) {
  129 +// WZp wZp = wZpDao.selectById(wDdb.getfZpid());
  130 +// wZp.setfZt("定制中");
  131 +// wZpDao.updateById(wZp);
  132 +// }
  133 + return WxPayNotifyResponse.success("成功");
  134 + } catch (WxPayException e) {
  135 + return WxPayNotifyResponse.fail(e.getErrCodeDes());
  136 + }
  137 + }
  138 +}
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/util/LocalDateTimeUtils.java 0 → 100644
... ... @@ -0,0 +1,92 @@
  1 +package com.hotent.lpg.user.util;
  2 +
  3 +import java.time.Instant;
  4 +import java.time.LocalDateTime;
  5 +import java.time.ZoneId;
  6 +import java.time.format.DateTimeFormatter;
  7 +import java.time.format.DateTimeFormatterBuilder;
  8 +import java.time.temporal.ChronoField;
  9 +
  10 +/**
  11 + * LocalDateTime时间工具
  12 + */
  13 +public class LocalDateTimeUtils {
  14 +
  15 + public static final String YYYY = "yyyy";
  16 + public static final String YYYYMM = "yyyyMM";
  17 + public static final String YYYYMMDD = "yyyyMMdd";
  18 + public static final String YYYYMMDDHH = "yyyyMMddHH";
  19 + public static final String YYYYMMDDHHMM = "yyyyMMddHHmm";
  20 + public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
  21 + public static final String YYYY_MM = "yyyy-MM";
  22 + public static final String YYYY_MM_DD = "yyyy-MM-dd";
  23 + public static final String YYYY_MM_DD_HH = "yyyy-MM-dd HH";
  24 + public static final String YYYY_MM_DD_HH_MM = "yyyy-MM-dd HH:mm";
  25 + public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
  26 +
  27 + private static final String BASE_TIME_FORMAT = "[yyyyMMddHHmmss][yyyyMMddHHmm][yyyyMMddHH][yyyyMMdd][yyyyMM][yyyy][[-][/][.]MM][[-][/][.]dd][ ][HH][[:][.]mm][[:][.]ss][[:][.]SSS]";
  28 + /**
  29 + * 【推荐】解析常用时间字符串,支持,并不局限于以下形式:
  30 + * [yyyy][yyyy-MM][yyyy-MM-dd][yyyy-MM-dd HH][yyyy-MM-dd HH:mm][yyyy-MM-dd HH:mm:ss][yyyy-MM-dd HH:mm:ss:SSS]
  31 + * [yyyy][yyyy/MM][yyyy/MM/dd][yyyy/MM/dd HH][yyyy/MM/dd HH:mm][yyyy/MM/dd HH:mm:ss][yyyy/MM/dd HH:mm:ss:SSS]
  32 + * [yyyy][yyyy.MM][yyyy.MM.dd][yyyy.MM.dd HH][yyyy.MM.dd HH.mm][yyyy.MM.dd HH.mm.ss][yyyy.MM.dd HH.mm.ss.SSS]
  33 + * [yyyy][yyyyMM][yyyyMMdd][yyyyMMddHH][yyyyMMddHHmm][yyyyMMddHHmmss]
  34 + * [MM-dd]
  35 + * 不支持yyyyMMddHHmmssSSS,因为本身DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS")就不支持这个形式
  36 + *
  37 + * @param timeString
  38 + * @return
  39 + */
  40 + public static LocalDateTime parse(String timeString) {
  41 + return LocalDateTime.parse(timeString, getDateTimeFormatterByPattern(BASE_TIME_FORMAT));
  42 + }
  43 +
  44 + /**
  45 + * 根据传进来的pattern返回LocalDateTime,自动补齐
  46 + *
  47 + * @param timeString
  48 + * @param pattern
  49 + * @return
  50 + */
  51 + public static LocalDateTime parseByPattern(String timeString, String pattern) {
  52 + return LocalDateTime.parse(timeString, getDateTimeFormatterByPattern(pattern));
  53 + }
  54 +
  55 + private static DateTimeFormatter getDateTimeFormatterByPattern(String pattern) {
  56 + return new DateTimeFormatterBuilder()
  57 + .appendPattern(pattern)
  58 + .parseDefaulting(ChronoField.YEAR_OF_ERA, LocalDateTime.now().getYear())
  59 + .parseDefaulting(ChronoField.MONTH_OF_YEAR, LocalDateTime.now().getMonthValue())
  60 + .parseDefaulting(ChronoField.DAY_OF_MONTH, 1)
  61 + .parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
  62 + .parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0)
  63 + .parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0)
  64 + .parseDefaulting(ChronoField.NANO_OF_SECOND, 0)
  65 + .toFormatter();
  66 + }
  67 +
  68 + /**
  69 + * 将timestamp转为LocalDateTime
  70 + * @param timestamp
  71 + * @return
  72 + */
  73 + public static LocalDateTime timestamToDatetime(long timestamp){
  74 + Instant instant = Instant.ofEpochMilli(timestamp);
  75 + return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
  76 + }
  77 +
  78 + /**
  79 + * 将LocalDataTime转为timestamp
  80 + * @param ldt
  81 + * @return
  82 + */
  83 + public static long datatimeToTimestamp(LocalDateTime ldt){
  84 + ZoneId zone = ZoneId.systemDefault();
  85 + return ldt.atZone(zone).toInstant().toEpochMilli();
  86 + }
  87 +
  88 + public static void main(String[] args) {
  89 + long timeStamp = 1382694957000l;
  90 + System.out.println(timestamToDatetime(timeStamp));
  91 + }
  92 +}
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/util/WxPayConfiguration.java 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +package com.hotent.lpg.user.util;
  2 +
  3 +import com.github.binarywang.wxpay.config.WxPayConfig;
  4 +import com.github.binarywang.wxpay.service.WxPayService;
  5 +import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
  6 +
  7 +public class WxPayConfiguration {
  8 +// public static final String appId = "wxf41ff374261f39cc"; // 该配置用的是景易游的微信支付信息
  9 + public static final String appId = "wxde6f31c15afb357d";
  10 +
  11 + public static WxPayService getPayService() {
  12 + // 该配置用的是景易游的微信支付信息
  13 +// WxPayConfig wxPayConfig = new WxPayConfig();
  14 +// wxPayConfig.setAppId("wxf41ff374261f39cc");
  15 +// wxPayConfig.setMchId("1634368190");
  16 +// wxPayConfig.setMchKey("Peony8228Peony8228Peony8228Peony");
  17 +//// wxPayConfig.setKeyPath("/mnt/install/joolun-file/cert/1/apiclient_cert8e55f27b-6d67-4b91-a16e-e9f6ef96ca5b11027923844080776299.p12");
  18 +//// wxPayConfig.setPrivateKeyPath("/mnt/install/joolun-file/cert/1/apiclient_key571e2a52-a9f8-46c5-9d4d-ed4b08d0749c4331609001879503591.pem");
  19 +//// wxPayConfig.setPrivateCertPath("/mnt/install/joolun-file/cert/1/apiclient_cert13b610c6-4005-4189-8a61-85fab73fa42017841178972810569411.pem");
  20 +// wxPayConfig.setCertSerialNo("55ED43DE3CC79DD045B92577A8FB2E95AACE8BEF");
  21 +// wxPayConfig.setApiV3Key("Peony8228Peony8228Peony8228Peony");
  22 +// // 可以指定是否使用沙箱环境
  23 +// wxPayConfig.setUseSandboxEnv(false);
  24 +
  25 +
  26 + /**
  27 + * 商户简称:
  28 + * 牡丹集团宁安智慧工程中心
  29 + * 企业名称:
  30 + * 北京牡丹电子集团有限责任公司宁安智慧工程中心
  31 + * 登录账号
  32 + * 1556251121 (本账号)
  33 + *
  34 + * 账号角色
  35 + * Administrator
  36 + * 创建时间
  37 + * 2019年9月19日 09:29:32
  38 + * 绑定微信号
  39 + * c*****21更换绑定
  40 + * 姓 名
  41 + * *际
  42 + * 联系手机
  43 + * 158******80
  44 + * 联系邮箱
  45 + * b*********n
  46 + */
  47 + WxPayConfig wxPayConfig = new WxPayConfig();
  48 + wxPayConfig.setAppId("wxde6f31c15afb357d"); // appId(应用id)(微信支付商户平台获取)
  49 + wxPayConfig.setMchId("1556251121"); // 商户号(微信支付商户平台获取)
  50 + // 这里的密钥应该使用APIv2密码,v3密钥此jar包不支持签名方式
  51 + wxPayConfig.setMchKey("Peony8228Peony8228Peony8228Peony"); // 商户密钥(APIv2密钥)(微信支付商户平台-》账户中心-》API安全中获取APIv3密钥)
  52 +// wxPayConfig.setKeyPath("/mnt/install/joolun-file/cert/1/apiclient_cert8e55f27b-6d67-4b91-a16e-e9f6ef96ca5b11027923844080776299.p12");
  53 +// wxPayConfig.setPrivateKeyPath("/mnt/install/joolun-file/cert/1/apiclient_key571e2a52-a9f8-46c5-9d4d-ed4b08d0749c4331609001879503591.pem");
  54 +// wxPayConfig.setPrivateCertPath("/mnt/install/joolun-file/cert/1/apiclient_cert13b610c6-4005-4189-8a61-85fab73fa42017841178972810569411.pem");
  55 + wxPayConfig.setCertSerialNo("736846A3CE4CBAC36DD5E81EB08F89240E4A05E1"); // 商户证书序列号(微信支付商户平台-》账户中心-》API安全中申请API证书)
  56 + wxPayConfig.setApiV3Key("Peony8228Peony8228Peony8228Peony"); // 商户密钥(APIv2密钥)(微信支付商户平台-》账户中心-》API安全中获取APIv3密钥)
  57 + // 可以指定是否使用沙箱环境
  58 + wxPayConfig.setUseSandboxEnv(false);
  59 + WxPayService wxPayService = new WxPayServiceImpl();
  60 + wxPayService.setConfig(wxPayConfig);
  61 + return wxPayService;
  62 + }
  63 +}
... ...
backend/lpg-user/src/main/java/com/hotent/lpg/user/vo/ResultData.java 0 → 100644
... ... @@ -0,0 +1,42 @@
  1 +package com.hotent.lpg.user.vo;
  2 +
  3 +import lombok.Data;
  4 +import lombok.experimental.Accessors;
  5 +
  6 +import java.io.Serializable;
  7 +import java.util.HashMap;
  8 +
  9 +/**
  10 + * @projectName: service
  11 + * @package: com.hotent.common
  12 + * @className: ResultData
  13 + * @author: HuangLang
  14 + * @description: 接口统一返回对象
  15 + * @date: 2021-12-15 13:40
  16 + */
  17 +@Data
  18 +@Accessors(chain = true)
  19 +public class ResultData implements Serializable {
  20 +
  21 + private String code ="200";
  22 + private String msg ="success";
  23 + private Object data =new HashMap<>();
  24 +
  25 + public static ResultData error(Exception e){
  26 + return new ResultData().setCode("500").setMsg(e.getMessage());
  27 + }
  28 +
  29 + public static ResultData error(String message){
  30 + return new ResultData().setCode("500").setMsg(message);
  31 + }
  32 +
  33 + public static ResultData success(){
  34 + return new ResultData();
  35 + }
  36 +
  37 + public static ResultData success(Object o){
  38 + return new ResultData().setData(o);
  39 + }
  40 +
  41 +
  42 +}
... ...