pom.xml
@@ -28,6 +28,13 @@ </properties> <dependencies> <!-- 微信支付 --> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-pay</artifactId> <version>4.4.0</version> </dependency> <dependency> <groupId>com.aliyun</groupId> <artifactId>dysmsapi20170525</artifactId> src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
@@ -5,6 +5,14 @@ @Getter public enum DataDictionaryEnum { /** * 微信设置 */ XCX_APP_ID("XCX_APP_ID", "XCX_APP_ID"), XCX_MCH_ID("XCX_MCH_ID", "XCX_MCH_ID"), XCX_MCH_KEY("XCX_MCH_KEY", "XCX_MCH_KEY"), XCX_MCH_KEY_PATH_P12("XCX_MCH_KEY_PATH_P12", "XCX_MCH_KEY_PATH_P12"), XCX_NOTICE_URL("XCX_NOTICE_URL", "XCX_NOTICE_URL"), //微信订阅模板ID, // 微信订单通知 // WX_TEMPLATE_ID_ONE("WX_TEMPLATE", "WX_TEMPLATE_ID_ONE"), src/main/java/cc/mrbird/febs/mall/controller/ApiMallAppController.java
@@ -92,4 +92,10 @@ return mallAppService.getOrderCancel(apiGetOrderDto); } @ApiOperation(value = "支付", notes = "支付") @PostMapping(value = "/wxCodePay") public FebsResponse wxCodePay(@RequestBody ApiWxCodePayDto wxCodePayDto) { return mallAppService.wxCodePay(wxCodePayDto); } } src/main/java/cc/mrbird/febs/mall/dto/ApiWxCodePayDto.java
New file @@ -0,0 +1,16 @@ package cc.mrbird.febs.mall.dto; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @Data @ApiModel(value = "ApiWxCodePayDto", description = "新增订单接口参数接收类") public class ApiWxCodePayDto { @ApiModelProperty(value = "订单ID") private Long orderId; @ApiModelProperty(value = "微信条形码") private String wxPayCode; } src/main/java/cc/mrbird/febs/mall/service/IApiMallAppService.java
@@ -26,4 +26,6 @@ FebsResponse getOrder(ApiGetOrderDto apiGetOrderDto); FebsResponse getOrderCancel(ApiGetOrderDto apiGetOrderDto); FebsResponse wxCodePay(ApiWxCodePayDto wxCodePayDto); } src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallAppServiceImpl.java
@@ -13,6 +13,7 @@ import cc.mrbird.febs.mall.mapper.*; import cc.mrbird.febs.mall.service.IApiMallAppService; import cc.mrbird.febs.mall.vo.*; import cc.mrbird.febs.pay.service.IXcxCodePayService; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.ObjectUtil; @@ -47,6 +48,7 @@ private final MallOrderInfoMapper mallOrderInfoMapper; private final MallOrderItemMapper mallOrderItemMapper; private final MallMemberWalletMapper mallMemberWalletMapper; private final IXcxCodePayService xcxCodePayService; public static void main(String[] args) { System.out.println(SecureUtil.md5("a123456")); @@ -319,6 +321,25 @@ return new FebsResponse().success().message("订单已取消"); } @Override public FebsResponse wxCodePay(ApiWxCodePayDto wxCodePayDto) { Long orderId = wxCodePayDto.getOrderId(); MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectById(orderId); String wxPayCode = wxCodePayDto.getWxPayCode(); mallOrderInfo.setTakeCode(wxPayCode); List<ApiGetOrderOrderItemVo> appOrderItemByOrderId = mallOrderItemMapper.getAppOrderItemByOrderId(orderId); if(CollUtil.isEmpty(appOrderItemByOrderId)){ mallOrderInfo.setName("商品"); }else{ mallOrderInfo.setName(appOrderItemByOrderId.get(0).getGoodsName()); } mallOrderInfo.setPayResult("2"); mallOrderInfoMapper.updateById(mallOrderInfo); // 发起付款码支付请求 String payResult = xcxCodePayService.pay(mallOrderInfo); return new FebsResponse().success().message(payResult); } public String generateAsaToken(String token) { RSA rsa = new RSA(null, AppContants.PUBLIC_KEY); return rsa.encryptBase64(token + "_" + System.currentTimeMillis(), KeyType.PublicKey); src/main/java/cc/mrbird/febs/pay/configure/WxPayConfiguration.java
New file @@ -0,0 +1,59 @@ package cc.mrbird.febs.pay.configure; import cc.mrbird.febs.common.enumerates.DataDictionaryEnum; import cc.mrbird.febs.mall.entity.DataDictionaryCustom; import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper; import cn.hutool.core.util.StrUtil; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import lombok.AllArgsConstructor; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @ConditionalOnClass(WxPayService.class) @AllArgsConstructor public class WxPayConfiguration { private DataDictionaryCustomMapper dataDictionaryCustomMapper; @Bean @ConditionalOnMissingBean public WxPayService wxService() { String appId = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.XCX_APP_ID.getType(), DataDictionaryEnum.XCX_APP_ID.getCode() ).getValue(); String mchId = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.XCX_MCH_ID.getType(), DataDictionaryEnum.XCX_MCH_ID.getCode() ).getValue(); String mchKey = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.XCX_MCH_KEY.getType(), DataDictionaryEnum.XCX_MCH_KEY.getCode() ).getValue(); String keyPath = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.XCX_MCH_KEY_PATH_P12.getType(), DataDictionaryEnum.XCX_MCH_KEY_PATH_P12.getCode() ).getValue(); String notifyUrl = dataDictionaryCustomMapper.selectDicDataByTypeAndCode( DataDictionaryEnum.XCX_NOTICE_URL.getType(), DataDictionaryEnum.XCX_NOTICE_URL.getCode() ).getValue(); WxPayConfig payConfig = new WxPayConfig(); payConfig.setAppId(StrUtil.trim(appId)); payConfig.setMchId(StrUtil.trim(mchId)); payConfig.setMchKey(StrUtil.trim(mchKey)); payConfig.setKeyPath(StrUtil.trim(keyPath)); payConfig.setNotifyUrl(StrUtil.trim(notifyUrl)); // 可以指定是否使用沙箱环境 payConfig.setUseSandboxEnv(false); WxPayService wxPayService = new WxPayServiceImpl(); wxPayService.setConfig(payConfig); return wxPayService; } } src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java
@@ -19,6 +19,7 @@ import cc.mrbird.febs.pay.model.OrderStateMsgVo; import cc.mrbird.febs.pay.model.WxTemplateData; import cc.mrbird.febs.pay.service.IPayService; import cc.mrbird.febs.pay.service.IXcxCodePayService; import cc.mrbird.febs.pay.service.IXcxPayService; import cc.mrbird.febs.pay.util.PayThreadPool; import cc.mrbird.febs.pay.util.Signature; @@ -28,15 +29,17 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.*; import org.springframework.web.client.RestTemplate; import org.thymeleaf.engine.TemplateData; @@ -69,6 +72,12 @@ RedisUtils redisUtils; @Autowired private IApiMallMemberWalletService memberWalletService; @Autowired private WxPayService wxPayService; @Autowired private IXcxCodePayService xcxCodePayService; @Autowired private IXcxPayService iXcxPayService; @@ -289,4 +298,14 @@ out.close(); } @PostMapping(value = "/xcxCodePayCallBack") public String xcxCodePayCallBack(@RequestBody String xmlData) throws WxPayException { log.info("=======微信支付码付款回调:{}========", xmlData); WxPayOrderNotifyResult notifyResult = this.wxPayService.parseOrderNotifyResult(xmlData); xcxCodePayService.payCallback(notifyResult.toMap()); return WxPayNotifyResponse.success("成功"); } } src/main/java/cc/mrbird/febs/pay/service/IXcxCodePayService.java
New file @@ -0,0 +1,11 @@ package cc.mrbird.febs.pay.service; import cc.mrbird.febs.mall.entity.MallOrderInfo; import java.util.Map; public interface IXcxCodePayService { String pay(MallOrderInfo orderInfo); void payCallback(Map<String, String> params); } src/main/java/cc/mrbird/febs/pay/service/impl/xcxCodePayServiceImpl.java
New file @@ -0,0 +1,88 @@ package cc.mrbird.febs.pay.service.impl; import cc.mrbird.febs.common.enumerates.OrderStatusEnum; import cc.mrbird.febs.common.exception.FebsException; import cc.mrbird.febs.mall.entity.MallMember; import cc.mrbird.febs.mall.entity.MallOrderInfo; import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; import cc.mrbird.febs.pay.model.BrandWCPayRequestData; import cc.mrbird.febs.pay.model.JsApiPayBusiness; import cc.mrbird.febs.pay.model.JsApiPayReqData; import cc.mrbird.febs.pay.model.JsApiPayResData; import cc.mrbird.febs.pay.service.IXcxCodePayService; import cc.mrbird.febs.pay.util.WebUtil; import cn.hutool.core.date.DateField; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.github.binarywang.wxpay.bean.order.WxPayAppOrderResult; import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.math.BigDecimal; import java.util.Map; @Slf4j @Service @RequiredArgsConstructor public class xcxCodePayServiceImpl implements IXcxCodePayService { private final MallOrderInfoMapper mallOrderInfoMapper; private final WxPayService wxService; @Override public String pay(MallOrderInfo mallOrderInfo) { WxPayMicropayRequest request = new WxPayMicropayRequest(); request request.setAppid(wxPayProperties.getAppId()); request.setMchId(wxPayProperties.getMchId()); request.setNotifyUrl(wxPayProperties.getNoticeUrl()); request.setBody(orderInfo.getName()); request.setOutTradeNo(orderInfo.getOrderNo()); request.setTimeExpire(DateUtil.format(DateUtil.offset(new Date(), DateField.MINUTE, 15), DatePattern.PURE_DATETIME_PATTERN)); request.setSpbillCreateIp("127.0.0.1"); request.setTradeType("APP"); // if ("dev".equals(active) || "test".equals(active)) { if ("dev".equals(active)) { request.setTotalFee(1); } else { request.setTotalFee(orderInfo.getAmount().add(orderInfo.getCarriage()).multiply(new BigDecimal(100)).intValue()); } try { WxPayMicropayResult micropay = wxService.micropay(request); return JSONObject.toJSONString(micropay); } catch (WxPayException e) { e.printStackTrace(); throw new FebsException("支付异常, 请检查"); } return null; } @Override @Transactional(rollbackFor = Exception.class) public void payCallback(Map<String, String> params) { String orderNo = params.get("out_trade_no"); LambdaQueryWrapper<MallOrderInfo> query = new LambdaQueryWrapper<>(); query.eq(MallOrderInfo::getOrderNo, orderNo); MallOrderInfo orderInfo = mallOrderInfoMapper.selectOne(query); if ("1".equals(orderInfo.getPayResult())) { return; } orderInfo.setStatus(OrderStatusEnum.FINISH.getValue()); orderInfo.setPayResult("1"); orderInfo.setPayTime(DateUtil.date()); orderInfo.setPayTradeNo(params.get("transaction_id")); mallOrderInfoMapper.updateById(orderInfo); } }