pom.xml
@@ -281,6 +281,7 @@ <version>3.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java --> <dependency> <groupId>com.alipay.sdk</groupId> @@ -288,6 +289,30 @@ <version>4.40.82.ALL</version> </dependency> <dependency> <groupId>com.github.binarywang</groupId> <artifactId>weixin-java-pay</artifactId> <version>4.6.0</version> </dependency> <!-- https://mvnrepository.com/artifact/com.github.wechatpay-apiv3/wechatpay-java --> <!-- <dependency>--> <!-- <groupId>com.github.wechatpay-apiv3</groupId>--> <!-- <artifactId>wechatpay-java</artifactId>--> <!-- <version>0.2.15</version>--> <!-- </dependency>--> <dependency> <groupId>com.volcengine</groupId> <artifactId>ve-tos-java-sdk</artifactId> <version>2.8.8</version> </dependency> </dependencies> <build> src/main/java/com/mzl/flower/config/ResourceServerConfig.java
@@ -66,6 +66,10 @@ .antMatchers("/v2/config-param/base/info").permitAll() .antMatchers("/api/supplier/**").permitAll() .antMatchers("/api/customer/center").permitAll() // 微信支付暂时测试 .antMatchers("/v2/wechat/**").permitAll() .antMatchers("/api/**").authenticated();//配置访问控制,必须认证过后才可以访问 } src/main/java/com/mzl/flower/config/TosClientConfig.java
对比新文件 @@ -0,0 +1,22 @@ package com.mzl.flower.config; import com.volcengine.tos.TOSV2; import com.volcengine.tos.TOSV2ClientBuilder; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import javax.annotation.Resource; @Configuration public class TosClientConfig { @Resource private TosProperties properties; @Bean public TOSV2 tosClient() { return new TOSV2ClientBuilder().build(properties.getRegion(), properties.getEndpoint(), properties.getKeyid(), properties.getKeysecret()); } } src/main/java/com/mzl/flower/config/TosProperties.java
对比新文件 @@ -0,0 +1,18 @@ package com.mzl.flower.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @Component @ConfigurationProperties(prefix = "tos-oss") public class TosProperties { private String endpoint; private String region; private String keyid; private String keysecret; private String bucketname; } src/main/java/com/mzl/flower/config/pay/WechatAppProperties.java
对比新文件 @@ -0,0 +1,43 @@ package com.mzl.flower.config.pay; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; @Data @Configuration @ConfigurationProperties(prefix = "wechat-app") public class WechatAppProperties { /** * 商户号 */ private String merchantId; /** * 商户密钥 */ private String merchantKey; /** * appId */ private String appid; /** *密钥 */ private String secret; /** * */ private String tradeType; /** * 回调地址 */ private String notifyUrl; } src/main/java/com/mzl/flower/config/pay/WechatClientConfigurator.java
对比新文件 @@ -0,0 +1,41 @@ package com.mzl.flower.config.pay; import com.github.binarywang.wxpay.config.WxPayConfig; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @author Taojie * 微信APP支付 */ @Configuration public class WechatClientConfigurator { @Autowired private WechatAppProperties wechatProperties; @Bean public WxPayConfig wxPayConfig() { WxPayConfig payConfig = new WxPayConfig(); payConfig.setAppId(wechatProperties.getAppid()); payConfig.setMchId(wechatProperties.getMerchantId()); // 商户号 payConfig.setMchKey(wechatProperties.getMerchantKey()); // payConfig.setMchKey(wechatProperties.getSecret()); payConfig.setTradeType(wechatProperties.getTradeType()); payConfig.setNotifyUrl(wechatProperties.getNotifyUrl()); // 关键!APP支付必须指定 return payConfig; } @Bean public WxPayService wxPayService(WxPayConfig wxPayConfig) { WxPayService wxPayService = new WxPayServiceImpl(); wxPayService.setConfig(wxPayConfig); return wxPayService; } } src/main/java/com/mzl/flower/domain/CategoryConfig.java
对比新文件 @@ -0,0 +1,15 @@ package com.mzl.flower.domain; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor public class CategoryConfig { private Integer id; private String name; private Integer order; private Boolean isEnabled; } src/main/java/com/mzl/flower/domain/CategoryConfigDO.java
对比新文件 @@ -0,0 +1,29 @@ package com.mzl.flower.domain; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; import com.mzl.flower.base.BaseAutoEntity; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @Data @AllArgsConstructor @NoArgsConstructor @TableName("category_config") public class CategoryConfigDO extends BaseAutoEntity { @TableField("user_id") private String userId; @TableField("category_id") private Integer categoryId; private String name; @TableField("`order`") private Integer order; @TableField("is_enabled") private Boolean isEnabled; } src/main/java/com/mzl/flower/domain/CategoryConfigSync.java
对比新文件 @@ -0,0 +1,15 @@ package com.mzl.flower.domain; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.List; @Data @AllArgsConstructor @NoArgsConstructor public class CategoryConfigSync { private String userId; private List<CategoryConfig> categories; } src/main/java/com/mzl/flower/dto/request/UserPhoneLoginDTO.java
@@ -18,5 +18,8 @@ @ApiModelProperty(value = "用户类型") private String userType; @ApiModelProperty(value = "用户注销id") private String customUserId; } src/main/java/com/mzl/flower/dto/request/pay/PayQueryDTO.java
对比新文件 @@ -0,0 +1,25 @@ package com.mzl.flower.dto.request.pay; import io.swagger.annotations.ApiModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.math.BigDecimal; @Data @NoArgsConstructor @AllArgsConstructor public class PayQueryDTO { /** * 订单名称 */ @ApiModelProperty(value = "订单编号") @NotEmpty(message = "订单编号不能为空") private String outerOrderNo; } src/main/java/com/mzl/flower/dto/response/customer/CustomerDTO.java
@@ -74,4 +74,7 @@ @ApiModelProperty("我的邀请码") private String intervialcode; @ApiModelProperty("注销/非注销") private Boolean isClosed; } src/main/java/com/mzl/flower/entity/customer/Customer.java
@@ -52,6 +52,10 @@ private LocalDateTime memberOvertime; @ApiModelProperty("是否会员") private Boolean isMember; @ApiModelProperty("是否注销") private Boolean isClosed; @ApiModelProperty("我的邀请码") private String intervialcode; @ApiModelProperty("注册邀请码") src/main/java/com/mzl/flower/mapper/CategoryConfigMapper.java
对比新文件 @@ -0,0 +1,27 @@ package com.mzl.flower.mapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.mzl.flower.domain.CategoryConfigDO; import org.apache.ibatis.annotations.*; import org.springframework.stereotype.Repository; import java.util.List; @Repository public interface CategoryConfigMapper extends BaseMapper<CategoryConfigDO> { // @Insert("INSERT INTO category_config( user_id, category_id, name, `order`, is_enabled) " + "VALUES( #{userId}, #{categoryId}, #{name}, #{order}, #{isEnabled})") // void insert(CategoryConfigDO categoryConfigDO); // // @Update("UPDATE category_config SET name = #{name}, `order` = #{order}, " + "is_enabled = #{isEnabled} WHERE id = #{id}") // void update(CategoryConfigDO categoryConfigDO); // @Select("SELECT * FROM category_config WHERE id = #{id}") // CategoryConfigDO findById(Long id); @Select("SELECT * FROM category_config WHERE user_id = #{userId}") List<CategoryConfigDO> findByUserId(String userId); @Delete("DELETE FROM category_config WHERE user_id = #{userId}") void deleteByUserId(String userId); } src/main/java/com/mzl/flower/service/TosService.java
对比新文件 @@ -0,0 +1,72 @@ package com.mzl.flower.service; import com.mzl.flower.config.TosProperties; import com.mzl.flower.config.exception.ValidationException; import com.mzl.flower.utils.UUIDGenerator; import com.volcengine.tos.TOSV2; import com.volcengine.tos.TosClientException; import com.volcengine.tos.TosServerException; import com.volcengine.tos.model.object.PutObjectFromFileInput; import com.volcengine.tos.model.object.PutObjectFromFileOutput; import com.volcengine.tos.model.object.PutObjectInput; import com.volcengine.tos.model.object.PutObjectOutput; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import java.io.IOException; import java.io.InputStream; @Service public class TosService { @Autowired private TOSV2 tosClient; @Autowired private TosProperties tosProperties; private String upladPre="https://"; public TosService(TOSV2 tosClient) { this.tosClient = tosClient; } public String uploadFile(String objectKey, String filePath) throws IOException { try { PutObjectFromFileInput input = new PutObjectFromFileInput() .setBucket(tosProperties.getBucketname()).setKey(objectKey).setFilePath(filePath); PutObjectFromFileOutput output = tosClient.putObjectFromFile(input); return "Upload success! ETag: " + output.getEtag(); } catch (TosClientException | TosServerException e) { throw new IOException("Upload failed: " + e.getMessage(), e); } } public String uploadFile(InputStream inputStream, String fileName) throws IOException { try { //获取文件名称 String filename = fileName; //使文件名称唯一 String uuid = UUIDGenerator.getUUID(); filename = uuid + filename; String dir = uuid.substring(0, 2); filename = dir + "/" + filename; PutObjectInput putObjectInput = new PutObjectInput().setBucket(tosProperties.getBucketname()).setKey(filename).setContent(inputStream); PutObjectOutput output = tosClient.putObject(putObjectInput); // System.out.println("putObject succeed, object's etag is " + output.getEtag()); // System.out.println("putObject succeed, object's crc64 is " + output.getHashCrc64ecma()); // https://edu-mys.oss-cn-chengdu.aliyuncs.com/yy.JPG String url = upladPre+tosProperties.getBucketname() + "." + tosProperties.getEndpoint() + "/" + filename; return url; } catch (TosClientException | TosServerException e) { throw new ValidationException("上传到云服务器发生异常"); } } } src/main/java/com/mzl/flower/service/customer/CategoryConfigService.java
对比新文件 @@ -0,0 +1,11 @@ package com.mzl.flower.service.customer; import com.mzl.flower.domain.CategoryConfig; import com.mzl.flower.domain.CategoryConfigSync; import java.util.List; public interface CategoryConfigService { void saveOrUpdateCategoryConfig(CategoryConfigSync categoryConfigSync); List<CategoryConfig> getCategoryConfigsByUserId(String userId); } src/main/java/com/mzl/flower/service/customer/CategoryConfigServiceImpl.java
对比新文件 @@ -0,0 +1,67 @@ package com.mzl.flower.service.customer; import com.mzl.flower.domain.CategoryConfig; import com.mzl.flower.domain.CategoryConfigDO; import com.mzl.flower.domain.CategoryConfigSync; import com.mzl.flower.mapper.CategoryConfigMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.util.ArrayList; import java.util.List; @Service public class CategoryConfigServiceImpl implements CategoryConfigService { @Autowired private CategoryConfigMapper categoryConfigMapper; @Override @Transactional public void saveOrUpdateCategoryConfig(CategoryConfigSync categoryConfigSync) { if (categoryConfigSync == null || categoryConfigSync.getUserId() == null) { throw new IllegalArgumentException("用户ID不能为空"); } // 先删除该用户之前的所有分类配置 categoryConfigMapper.deleteByUserId(categoryConfigSync.getUserId()); // 然后插入新的分类配置 if (categoryConfigSync.getCategories() != null && !categoryConfigSync.getCategories().isEmpty()) { for (CategoryConfig clientCategory : categoryConfigSync.getCategories()) { CategoryConfigDO dbCategory = new CategoryConfigDO(); dbCategory.setUserId(categoryConfigSync.getUserId()); dbCategory.setCategoryId(clientCategory.getId()); dbCategory.setName(clientCategory.getName()); dbCategory.setOrder(clientCategory.getOrder()); dbCategory.setIsEnabled(clientCategory.getIsEnabled()); categoryConfigMapper.insert(dbCategory); } } } @Override public List<CategoryConfig> getCategoryConfigsByUserId(String userId) { if (userId == null) { throw new IllegalArgumentException("用户ID不能为空"); } List<CategoryConfigDO> dbCategories = categoryConfigMapper.findByUserId(userId); if (dbCategories == null || dbCategories.isEmpty()) { return new ArrayList<>(); } List<CategoryConfig> clientCategories = new ArrayList<>(); for (CategoryConfigDO dbCategory : dbCategories) { CategoryConfig clientCategory = new CategoryConfig(); clientCategory.setId(dbCategory.getCategoryId()); clientCategory.setName(dbCategory.getName()); clientCategory.setOrder(dbCategory.getOrder()); clientCategory.setIsEnabled(dbCategory.getIsEnabled()); clientCategories.add(clientCategory); } return clientCategories; } } src/main/java/com/mzl/flower/service/customer/CustomerService.java
@@ -302,4 +302,18 @@ } return sb.toString(); } public void updateMemberInfoByUserId(Customer customer) { if(null!= customer && StringUtils.isNotBlank(customer.getUserId())){ Customer byUserId = getByUserId(customer.getUserId()); if(null !=byUserId){ byUserId.setName(customer.getName()); byUserId.setCover(customer.getCover()); customerMapper.updateById(byUserId); }else{ throw new ValidationException("用户不存在"); } } } } src/main/java/com/mzl/flower/service/impl/pay/AlipayServiceImpl.java
对比新文件 @@ -0,0 +1,74 @@ package com.mzl.flower.service.impl.pay; import com.alipay.api.AlipayClient; import com.alipay.api.domain.AlipayMerchantSolcreditserviceprodOrderQueryModel; import com.alipay.api.domain.AlipayTradeQueryModel; import com.alipay.api.request.AlipayMerchantSolcreditserviceprodOrderQueryRequest; import com.alipay.api.request.AlipayTradeQueryRequest; import com.alipay.api.response.AlipayMerchantSolcreditserviceprodOrderQueryResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import com.mzl.flower.config.pay.AlipayProperties; import com.mzl.flower.service.pay.AlipayService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.util.ArrayList; import java.util.List; @Service @Slf4j public class AlipayServiceImpl implements AlipayService { @Autowired private AlipayProperties alipayProperties; @Autowired AlipayClient alipayClient; @Override public AlipayTradeQueryResponse queryOrderByOutOrderNo(String outOrderNo) { try { // 构造请求参数以调用接口 AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); AlipayTradeQueryModel model = new AlipayTradeQueryModel(); // 设置订单支付时传入的商户订单号 model.setOutTradeNo(outOrderNo); // 设置支付宝交易号 // model.setTradeNo("2014112611001004680 073956707"); // 设置查询选项 List<String> queryOptions = new ArrayList<String>(); queryOptions.add("trade_settle_info"); model.setQueryOptions(queryOptions); request.setBizModel(model); // 第三方代调用模式下请设置app_auth_token // request.putOtherTextParam("app_auth_token", "<-- 请填写应用授权令牌 -->"); AlipayTradeQueryResponse response = alipayClient.execute(request); System.out.println(response.getBody()); if (response.isSuccess()) { System.out.println("调用成功"); } else { System.out.println("调用失败"); // sdk版本是"4.38.0.ALL"及以上,可以参考下面的示例获取诊断链接 // String diagnosisUrl = DiagnosisUtils.getDiagnosisUrl(response); // System.out.println(diagnosisUrl); } return response; } catch (Exception e) { throw new RuntimeException(e); } } @Override public String notifyCallBack() { return ""; } } src/main/java/com/mzl/flower/service/pay/AlipayService.java
对比新文件 @@ -0,0 +1,12 @@ package com.mzl.flower.service.pay; import com.alipay.api.response.AlipayTradeQueryResponse; public interface AlipayService extends PayService { @Override AlipayTradeQueryResponse queryOrderByOutOrderNo(String outOrderNo); @Override String notifyCallBack(); } src/main/java/com/mzl/flower/service/pay/PayService.java
对比新文件 @@ -0,0 +1,12 @@ package com.mzl.flower.service.pay; public interface PayService { /** * 根据订单编号查询订单状态 * @param outOrderNo */ <T> T queryOrderByOutOrderNo(String outOrderNo); String notifyCallBack(); } src/main/java/com/mzl/flower/service/system/UserService.java
@@ -637,6 +637,7 @@ updateCustomerDTO.setUserId(user.getId()); updateCustomerDTO.setRegesterCode(dto.getIntevailCode()); //有效邀请码注册成功后赠送1天会员 updateCustomerDTO.setIsMember(false); if (!customerService.checkCode(dto.getIntevailCode())) { updateCustomerDTO.setIsMember(true); updateCustomerDTO.setMemberOvertime(LocalDateTime.now().plusDays(1)); src/main/java/com/mzl/flower/utils/wechatpay/CommonUtils.java
对比新文件 @@ -0,0 +1,48 @@ package com.mzl.flower.utils.wechatpay; import java.security.MessageDigest; import java.util.UUID; /** * 常用工具类的封装,md5,uuid等 */ public class CommonUtils { /** * 生成 uuid, 即用来标识一笔单,也用做 nonce_str * @return */ public static String generateUUID(){ String uuid = UUID.randomUUID().toString(). replaceAll("-","").substring(0,32); return uuid; } /** * md5常用工具类 * @param data * @return */ public static String MD5(String data){ try { MessageDigest md5 = MessageDigest.getInstance("MD5"); byte [] array = md5.digest(data.getBytes("UTF-8")); StringBuilder sb = new StringBuilder(); for (byte item : array) { sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3)); } return sb.toString().toUpperCase(); }catch (Exception e){ e.printStackTrace(); } return null; } } src/main/java/com/mzl/flower/utils/wechatpay/WxPayUtil.java
对比新文件 @@ -0,0 +1,166 @@ package com.mzl.flower.utils.wechatpay; import java.util.Map; import org.springframework.util.DigestUtils; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.transform.OutputKeys; import javax.xml.transform.Transformer; import javax.xml.transform.TransformerFactory; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.StringWriter; import java.util.*; /** * 微信支付工具类,xml转map,map转xml,生成签名 */ public class WxPayUtil { /** * XML格式字符串转换为Map * * @param strXML XML字符串 * @return XML数据转换后的Map * @throws Exception */ public static Map<String, String> xmlToMap(String strXML) throws Exception { try { Map<String, String> data = new HashMap<String, String>(); DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder(); InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8")); org.w3c.dom.Document doc = documentBuilder.parse(stream); doc.getDocumentElement().normalize(); NodeList nodeList = doc.getDocumentElement().getChildNodes(); for (int idx = 0; idx < nodeList.getLength(); ++idx) { Node node = nodeList.item(idx); if (node.getNodeType() == Node.ELEMENT_NODE) { org.w3c.dom.Element element = (org.w3c.dom.Element) node; data.put(element.getNodeName(), element.getTextContent()); } } try { stream.close(); } catch (Exception ex) { // do nothing } return data; } catch (Exception ex) { throw ex; } } /** * 将Map转换为XML格式的字符串 * * @param data Map类型数据 * @return XML格式的字符串 * @throws Exception */ public static String mapToXml(Map<String, String> data) throws Exception { DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder(); org.w3c.dom.Document document = documentBuilder.newDocument(); org.w3c.dom.Element root = document.createElement("xml"); document.appendChild(root); for (String key: data.keySet()) { String value = data.get(key); if (value == null) { value = ""; } value = value.trim(); org.w3c.dom.Element filed = document.createElement(key); filed.appendChild(document.createTextNode(value)); root.appendChild(filed); } TransformerFactory tf = TransformerFactory.newInstance(); Transformer transformer = tf.newTransformer(); DOMSource source = new DOMSource(document); transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); transformer.setOutputProperty(OutputKeys.INDENT, "yes"); StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); transformer.transform(source, result); String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", ""); try { writer.close(); } catch (Exception ex) { } return output; } /** * 生成微信支付sign * @return */ public static String createSign(SortedMap<String, String> params, String key){ StringBuilder sb = new StringBuilder(); Set<Map.Entry<String, String>> es = params.entrySet(); Iterator<Map.Entry<String,String>> it = es.iterator(); //生成 stringA="appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA"; while (it.hasNext()){ Map.Entry<String,String> entry = (Map.Entry<String,String>)it.next(); String k = (String)entry.getKey(); String v = (String)entry.getValue(); if(null != v && !"".equals(v) && !"sign".equals(k) && !"key".equals(k)){ sb.append(k+"="+v+"&"); } } sb.append("key=").append(key); String sign = CommonUtils.MD5(sb.toString()).toUpperCase(); return sign; } /** * 校验签名 * @param params * @param key * @return */ public static boolean isCorrectSign(SortedMap<String, String> params, String key){ String sign = createSign(params,key); String weixinPaySign = params.get("sign").toUpperCase(); return weixinPaySign.equals(sign); } public static String generateNonceStr() { return UUID.randomUUID().toString().replace("-", ""); } public static String generateSignature(Map<String, String> data, String key) throws Exception { // 1. 字典序排序 List<String> keys = new ArrayList<>(data.keySet()); Collections.sort(keys); // 2. 拼接字符串 StringBuilder sb = new StringBuilder(); for (String k : keys) { if (data.get(k) != null && !"".equals(data.get(k)) && !"sign".equals(k)) { sb.append(k).append("=").append(data.get(k)).append("&"); } } sb.append("key=").append(key); // 3. MD5加密 return DigestUtils.md5DigestAsHex(sb.toString().getBytes("UTF-8")).toUpperCase(); } } src/main/java/com/mzl/flower/web/customer/CategoryConfigController.java
对比新文件 @@ -0,0 +1,27 @@ package com.mzl.flower.web.customer; import com.mzl.flower.domain.CategoryConfig; import com.mzl.flower.domain.CategoryConfigSync; import com.mzl.flower.service.customer.CategoryConfigService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; @RestController @RequestMapping("/api/categoryConfig") public class CategoryConfigController { @Autowired private CategoryConfigService categoryConfigService; @PostMapping("/saveOrUpdate") public void saveOrUpdateCategoryConfig(@RequestBody CategoryConfigSync categoryConfigSync) { categoryConfigService.saveOrUpdateCategoryConfig(categoryConfigSync); } @GetMapping("/getByUserId/{userId}") public List<CategoryConfig> getCategoryConfigsByUserId(@PathVariable String userId) { return categoryConfigService.getCategoryConfigsByUserId(userId); } } src/main/java/com/mzl/flower/web/login/CustomerLoginController.java
@@ -8,6 +8,7 @@ import com.mzl.flower.base.cache.StringCacheClient; import com.mzl.flower.config.exception.BaseException; import com.mzl.flower.config.exception.ValidationException; import com.mzl.flower.config.security.SecurityUtils; import com.mzl.flower.config.security.token.PhoneAuthenticationToken; import com.mzl.flower.config.security.token.UserIdAuthenticationToken; import com.mzl.flower.config.security.token.WebAuthenticationToken; @@ -17,6 +18,8 @@ import com.mzl.flower.dto.request.UserPhoneLoginDTO; import com.mzl.flower.dto.response.customer.CustomerDTO; import com.mzl.flower.dto.response.wx.WxUserVO; import com.mzl.flower.dto.security.UserDTO; import com.mzl.flower.entity.customer.Customer; import com.mzl.flower.entity.system.User; import com.mzl.flower.mapper.customer.CustomerMapper; import com.mzl.flower.service.customer.CustomerService; @@ -28,6 +31,7 @@ import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.security.authentication.AuthenticationDetailsSource; @@ -283,10 +287,11 @@ } User user = userService.findByTel(tel, Constants.USER_TYPE.customer.name()); User user1 = null; String tokenCache =""; if(user == null){ loginDTO.setUserType(Constants.USER_TYPE.customer.name()); User user1 = userService.registPhoneUser(loginDTO); user1 = userService.registPhoneUser(loginDTO); if(org.springframework.util.StringUtils.isEmpty(user1)){ throw new ValidationException("注册用户信息报错"); } @@ -311,6 +316,8 @@ if (currentCustomer.getIsEnabled() == false) { throw new ValidationException("用户已禁用,请联系管理员"); } tokenCache = stringCacheClient.get(TOKEN_KEY + SEPARATOR + user.getId()); if (StringUtils.isNotBlank(tokenCache)) { //强制删除token,下线 @@ -324,7 +331,11 @@ OAuth2AccessToken token = loginService.getAccessToken(authentication, Constants.USER_TYPE.customer.name()); //删除缓存中的验证码 stringCacheClient.delete(SMS_CODE_KEY + SEPARATOR + Constants.USER_TYPE.customer.name() + SEPARATOR + tel); stringCacheClient.set(TOKEN_KEY + SEPARATOR + user.getId(),token.getValue()); if(user == null){ stringCacheClient.set(TOKEN_KEY + SEPARATOR + user1.getId(),token.getValue()); }else { stringCacheClient.set(TOKEN_KEY + SEPARATOR + user.getId(), token.getValue()); } return returnData(R.SUCCESS.getCode(),token); }catch (UsernameNotFoundException e){ throw new ValidationException("用户不存在"); @@ -333,4 +344,50 @@ throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"登录错误"); } } } @PostMapping("/account/close") @ApiOperation(value = "账户注销", notes = "账户注销") public ResponseEntity<ReturnDataDTO<Boolean>> accountClose() { String userId = SecurityUtils.getUserId(); if(StringUtils.isNotBlank(userId)){ // CustomerDTO currentCustomer = customerMapper.getCurrentCustomer(userId); if(null==currentCustomer){ throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"用户不存在"); } currentCustomer.setIsClosed(true); User user=userService.getUserById(userId); if (StringUtils.isNotBlank(user.getLoginName())) { currentCustomer.setName("智信-" + user.getLoginName().substring(user.getLoginName().length() - 4)); } currentCustomer.setCover("https://hmy-flower.oss-cn-shanghai.aliyuncs.com/8f/8f205ea4618b4ce48d5bd204ae73f075tmp_f0c47a66148245dc17d74563c5939e764273ba583619664d.jpg"); Customer customer=new Customer(); BeanUtils.copyProperties(currentCustomer,customer); // 会员注销 customer.setIsMember(false); // 会员过期时间设置为空 customer.setMemberOvertime(null); customerMapper.updateById(customer); return returnData(R.SUCCESS.getCode(),true); }else{ throw new BaseException(R.RUNTIME_EXCEPTION.getCode(),"用户ID不能为空"); } } } src/main/java/com/mzl/flower/web/supplier/SupplierController.java
@@ -9,11 +9,15 @@ import com.mzl.flower.constant.Constants; import com.mzl.flower.dto.request.supplier.*; import com.mzl.flower.dto.response.supplier.SupplierDTO; import com.mzl.flower.entity.customer.Customer; import com.mzl.flower.service.TosService; import com.mzl.flower.service.customer.CustomerService; import com.mzl.flower.service.supplier.SupplierService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -35,6 +39,12 @@ // private static final R ALLOWED_CONTENT_TYPES = R.valueOf("jpg"); private final SupplierService supplierService; @Autowired private CustomerService customerService; @Autowired private TosService tosService; public SupplierController(SupplierService supplierService) { this.supplierService = supplierService; @@ -79,15 +89,24 @@ // } // 3. 生成文件名 String fileName = "avatar/" + UUID.randomUUID().toString() + getFileExtension(avatar.getOriginalFilename()); String originalFilename = avatar.getOriginalFilename(); // 原始文件名可能没有后缀 String contentType = avatar.getContentType(); // 例如 image/jpeg String extension = getExtensionFromContentType(contentType); // 我们下面实现这个方法 String newFileName = originalFilename + (extension != null ? extension : ""); // 4. 上传到 OSS //avatarUrl = ossService.uploadFile(fileName, avatar.getInputStream()); avatarUrl = tosService.uploadFile( avatar.getInputStream(),newFileName); } // 5. 更新用户信息 //supplierService.operationUpdate(nickname, avatarUrl); // supplierService.operationUpdate(nickname, avatarUrl); String userId = SecurityUtils.getUserId(); Customer customer=new Customer(); customer.setUserId(userId); customer.setCover(avatarUrl); customer.setName(nickname); customerService.updateMemberInfoByUserId(customer); return returnData(R.SUCCESS.getCode(),null); } catch (Exception e) { @@ -96,6 +115,27 @@ } } private String getExtensionFromContentType(String contentType) { if (contentType == null) return null; switch (contentType) { case "image/jpeg": return ".jpg"; case "image/png": return ".png"; case "image/gif": return ".gif"; case "image/webp": return ".webp"; case "image/bmp": return ".bmp"; default: return ".png"; } } @GetMapping("/page") @ApiOperation(value = "运营端-供应商分页查询", notes = "运营端-供应商分页查询") public ResponseEntity<ReturnDataDTO<Page<SupplierDTO>>> querySupplier(QuerySupplierDTO dto, Page page) { src/main/java/com/mzl/flower/web/v2/pay/AlipayController.java
@@ -7,12 +7,15 @@ import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.response.AlipayTradeAppPayResponse; import com.alipay.api.response.AlipayTradeQueryResponse; import com.mzl.flower.base.BaseController; import com.mzl.flower.base.R; import com.mzl.flower.config.pay.AlipayProperties; import com.mzl.flower.dto.request.pay.PayQueryDTO; import com.mzl.flower.dto.request.productOrders.ProductOrdersCreateDTO; import com.mzl.flower.entity.productOrders.ProductOrdersDO; import com.mzl.flower.enums.PayTypeEnum; import com.mzl.flower.service.pay.AlipayService; import com.mzl.flower.service.productOrders.ProductOrdersService; import com.mzl.flower.utils.alipay.OrderInfoUtil2_0; import io.swagger.annotations.Api; @@ -46,6 +49,9 @@ @Autowired private ProductOrdersService productOrdersService; @Autowired private AlipayService alipayService; /** * 获取订单支付请求参数 @@ -96,6 +102,18 @@ * @return * @throws Exception */ @PostMapping(value = "/order/status") @ApiOperation(value = "订单状态") public AlipayTradeQueryResponse queryOrderByOutOrderNo(@Validated @RequestBody PayQueryDTO payQueryDTO, HttpServletRequest request) throws Exception{ AlipayTradeQueryResponse response=alipayService.queryOrderByOutOrderNo(payQueryDTO.getOuterOrderNo()); return response; } /** * 支付宝回调url * @param request * @return * @throws Exception */ @PostMapping(value = "/notify") @ApiOperation(value = "支付宝回调url") public String notify(HttpServletRequest request) throws Exception{ src/main/java/com/mzl/flower/web/v2/pay/WechatPayController.java
对比新文件 @@ -0,0 +1,139 @@ package com.mzl.flower.web.v2.pay; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.domain.AlipayTradeAppPayModel; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.response.AlipayTradeAppPayResponse; import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest; import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.mzl.flower.base.BaseController; import com.mzl.flower.base.R; import com.mzl.flower.config.pay.AlipayProperties; import com.mzl.flower.dto.request.productOrders.ProductOrdersCreateDTO; import com.mzl.flower.entity.productOrders.ProductOrdersDO; import com.mzl.flower.enums.PayTypeEnum; import com.mzl.flower.service.productOrders.ProductOrdersService; import com.mzl.flower.utils.wechatpay.WxPayUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletRequest; import java.util.*; /** * @author taojie 20250321 */ @RestController @RequestMapping(value = "/v2/wechat") @Api(tags = {"微信支付相关"}) public class WechatPayController extends BaseController { private Logger logger = LoggerFactory.getLogger(WechatPayController.class); @Autowired private WxPayService wxPayService; @Autowired private ProductOrdersService productOrdersService; /** * 获取订单支付请求参数 * @param * @return * @throws Exception */ @PostMapping(value = "/pay-order-info") @ApiOperation(value = "获取订单支付请求参数") public ResponseEntity getPayOrderInfo(@Validated @RequestBody ProductOrdersCreateDTO productOrdersCreateDTO) throws Exception { ProductOrdersDO productOrdersDTO=new ProductOrdersDO(); BeanUtils.copyProperties(productOrdersCreateDTO,productOrdersDTO); productOrdersDTO.setPaymentMethod(PayTypeEnum.WECHAT.getName()); ProductOrdersDO productOrdersDO=productOrdersService.createProductOrders(productOrdersDTO); // 1. 构建请求对象 // WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() // .outTradeNo(productOrdersDO.getOrderNo()) // .totalFee(productOrdersDO.getCurrentPrice().intValue()*100) // 单位:分,1元 = 100分 // .body(productOrdersDO.getOrderType()+"_"+productOrdersDO.getCurrentPrice()) // .spbillCreateIp("127.0.0.1") // .tradeType("APP") // .notifyUrl(wxPayService.getConfig().getNotifyUrl()) // .build(); // 1. 构建请求对象 WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder() .outTradeNo("11111111111") .totalFee(1) // 单位:分,1元 = 100分 .body("商品描述") .spbillCreateIp("127.0.0.1") .tradeType("APP") .notifyUrl(wxPayService.getConfig().getNotifyUrl()) .build(); try { // 2. 请求统一下单接口 WxPayUnifiedOrderResult result = wxPayService.unifiedOrder(request); // 3. 构造给客户端的支付参数(Map 形式,客户端直接传给微信SDK) Map<String, String> appPayParams = createAppPayParams(result); return returnData(R.SUCCESS.getCode(), appPayParams); } catch (AlipayApiException e) { e.printStackTrace(); logger.error(e.getMessage(), e); return returnData(R.RUNTIME_EXCEPTION.getCode(), "",e.getMessage()); } } public Map<String, String> createAppPayParams(WxPayUnifiedOrderResult result) throws Exception { String prepayId = result.getPrepayId(); // 获取统一下单返回的prepay_id String nonceStr = WxPayUtil.generateNonceStr(); // 随机字符串 long timestamp = System.currentTimeMillis() / 1000; // 当前时间戳(秒) // 构建支付参数 SortedMap<String, String> payParams = new TreeMap<>(); payParams.put("appid", wxPayService.getConfig().getAppId()); // 微信公众号APPID payParams.put("partnerid", wxPayService.getConfig().getMchId()); // 商户号 payParams.put("prepayid", prepayId); // 统一下单接口返回的prepay_id payParams.put("package", "Sign=WXPay"); // 固定值 payParams.put("noncestr", nonceStr); // 随机字符串 payParams.put("timestamp", String.valueOf(timestamp)); // 时间戳 // 使用商户API密钥生成签名 String sign = WxPayUtil.generateSignature(payParams, wxPayService.getConfig().getMchKey()); payParams.put("sign", sign); // 签名 return payParams; } /** * 支付宝回调url * @param request * @return * @throws Exception */ @PostMapping(value = "/notify") @ApiOperation(value = "微信回调url") public String notify(HttpServletRequest request) throws Exception{ return null; } } src/main/resources/application.yml
@@ -65,6 +65,15 @@ keysecret: BrY0BM4pvDXhVKOMLsXzgzlhVe1keQ bucketname: hmy-flower #https://www.volcengine.com/docs/6349/107356 tos-oss: endpoint: tos-cn-beijing.volces.com region: cn-beijing keyid: AKLTNTFmOTFkMDg3ZDRmNGZkMmFkOTBmMTcyZmM4N2MyMmY keysecret: TW1FelpUY3lOalkxWWpjMk5HWTNOV0ZtWVdWa1lURTNNRE13WVdJMVkySQ== bucketname: smart-manager-new # bucketname: zhixinguanjia wx: miniapp: appid: wx1441324401626290 #小程序appId 花店端 @@ -85,6 +94,7 @@ supplier: appid: wx3203fd935a6ffe09 #小程序appId secret: 9121c703fb0c416b21a8c289dd73ae9b #secret sms: verificationCode: SMS_301300012 #验证码通用模版 @@ -111,4 +121,12 @@ publicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAoXlmlW2TI0DmYm/eZqGxHSPEdzULsrCTFPW2B4VrMk5gj8afPS/nq/cXEOIjsCrTP0dJsdbDqk+YlVRGEHCxgkl6nZGgRtZmzHJxwWw+YEMejI/fP0Sr8nKSEa/+otcX6LO7ktl4vVcvAU0Q9RVEGLpz62djkkwrJMMds6wSRsJI1GDwT+5Ra4s06+lVN4ISU0IUx6E2m2NaZBimMiB+buy7ZPXg6eDE5B2oXOQ5qdL2E18Q7hm7XI+DYAQslLXGr2pjLGLRZ01/b4XyIPzZmusNF+vNp4qKji38a23MjO33ONWqBj/JlWkPW5Vl1AiL5vg6HuqEEfHdBq9mVuZBEwIDAQAB gatewayUrl: https://openapi.alipay.com/gateway.do sandboxGatewayUrl: https://openapi-sandbox.dl.alipaydev.com/gateway.do notifyUrl: http://azcbit.natappfree.cc/jshERP-boot/alipay/notify notifyUrl: http://ta5p5m.natappfree.cc/flower/v2/alipay/notify wechat-app: merchantId: 1711247186 merchantKey: 6m8HhGNmk2S4sNPkwNJpawrCGUrnWNyV appid: wx7f9c8a2e924a4815 #小程序appId secret: 208d5eb98918856a6ac95ee01deba3ad #secret notifyUrl: http://ta5p5m.natappfree.cc/flower/v2/alipay/notify tradeType: APP