From 3280d1bd977e8fb5c9c60e615612fabb7b99c3e3 Mon Sep 17 00:00:00 2001 From: xiaoyong931011 <15274802129@163.com> Date: Wed, 27 Jul 2022 09:46:58 +0800 Subject: [PATCH] 20220727 保存代码 --- src/main/resources/templates/febs/views/modules/leader/leaderUpdate.html | 143 + src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java | 22 src/main/java/cc/mrbird/febs/mall/vo/AdminMallTeamLeaderVo.java | 40 src/main/java/cc/mrbird/febs/mall/dto/ApiXcxPhoneLoginDto.java | 16 src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderConfirmDto.java | 15 src/main/java/cc/mrbird/febs/pay/model/JsApiPayComReqData.java | 179 + src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java | 23 src/main/resources/application-prod.yml | 9 src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java | 7 src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java | 11 src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java | 3 src/main/java/cc/mrbird/febs/mall/service/IAdminMallTeamLeaderService.java | 23 src/main/java/cc/mrbird/febs/pay/model/JsApiPayBusiness.java | 141 + src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java | 93 src/main/java/cc/mrbird/febs/mall/dto/ApiApplayLeaderDto.java | 53 src/main/java/cc/mrbird/febs/pay/service/IServiceRequest.java | 20 src/main/java/cc/mrbird/febs/pay/service/impl/ScanPayQueryService.java | 29 src/main/resources/application-dev.yml | 9 src/main/java/cc/mrbird/febs/mall/entity/MallGroupJoinMember.java | 25 src/main/java/cc/mrbird/febs/pay/model/RefundResData.java | 168 + src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderTitleDto.java | 22 src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryReqData.java | 125 + src/main/java/cc/mrbird/febs/pay/service/impl/RefundService.java | 33 src/main/java/cc/mrbird/febs/pay/util/WechatConfigure.java | 53 src/main/java/cc/mrbird/febs/pay/model/JsApiPayReqData.java | 298 +++ src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java | 2 src/main/java/cc/mrbird/febs/mall/vo/AdminMallOrderInfoVo.java | 2 src/main/java/cc/mrbird/febs/mall/controller/ViewMallTeamLeaderController.java | 44 src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java | 4 src/main/java/cc/mrbird/febs/pay/model/JsApiPayComResData.java | 207 ++ src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryResData.java | 236 ++ src/main/resources/mapper/modules/MallMemberMapper.xml | 7 src/main/resources/mapper/modules/MallOrderInfoMapper.xml | 56 src/main/resources/application-test.yml | 13 src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderListVo.java | 50 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java | 172 + src/main/java/cc/mrbird/febs/pay/service/impl/BaseService.java | 47 src/main/java/cc/mrbird/febs/pay/util/Signature.java | 144 + src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderListDto.java | 29 src/main/java/cc/mrbird/febs/pay/util/WebUtil.java | 298 +++ src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java | 34 src/main/resources/templates/febs/views/modules/order/orderList.html | 63 src/main/java/cc/mrbird/febs/mall/controller/ViewGroupController.java | 13 src/main/java/cc/mrbird/febs/mall/service/IAdminGroupService.java | 7 src/main/java/cc/mrbird/febs/pay/util/XMLParser.java | 84 src/main/java/cc/mrbird/febs/mall/entity/MallGroup.java | 29 src/main/java/cc/mrbird/febs/pay/util/Util.java | 119 + src/main/java/cc/mrbird/febs/mall/controller/AdminMallTeamLeaderController.java | 60 src/main/resources/mapper/modules/MallTeamLeaderMapper.xml | 169 + src/main/java/cc/mrbird/febs/mall/service/impl/AdminGroupServiceImpl.java | 17 src/main/java/cc/mrbird/febs/mall/vo/ApiMallleaderStateVo.java | 14 src/main/java/cc/mrbird/febs/pay/model/BrandWCPayRequestData.java | 117 + src/main/java/cc/mrbird/febs/pay/service/IXcxPayService.java | 12 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java | 21 src/main/java/cc/mrbird/febs/mall/controller/ApiMallTeamLeaderController.java | 115 + src/main/java/cc/mrbird/febs/mall/dto/MallOrderInfoDto.java | 4 src/main/java/cc/mrbird/febs/pay/util/MD5.java | 59 pom.xml | 11 src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderListDto.java | 31 src/main/java/cc/mrbird/febs/mall/controller/AdminGroupController.java | 20 src/main/java/cc/mrbird/febs/pay/model/RefundReqData.java | 192 + src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java | 131 + src/main/java/cc/mrbird/febs/mall/conversion/MallTeamLeaderConversion.java | 26 src/main/java/cc/mrbird/febs/mall/dto/AddOrderDto.java | 6 src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java | 9 src/main/java/cc/mrbird/febs/mall/dto/OrderListDto.java | 4 src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallTeamLeaderServiceImpl.java | 165 + src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java | 57 src/main/java/cc/mrbird/febs/mall/service/IApiMallTeamLeaderService.java | 27 src/main/java/cc/mrbird/febs/pay/util/WeixinServiceUtil.java | 151 + src/main/resources/templates/febs/views/modules/leader/leaderList.html | 185 + src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java | 2 src/main/java/cc/mrbird/febs/pay/model/NotifyData.java | 145 + src/main/java/cc/mrbird/febs/pay/util/PayThreadPool.java | 46 src/main/java/cc/mrbird/febs/pay/util/RandomStringGenerator.java | 23 src/main/java/cc/mrbird/febs/mall/vo/AdminSelectListLeaderVo.java | 14 src/main/java/cc/mrbird/febs/mall/mapper/MallGroupMapper.java | 7 src/main/java/cc/mrbird/febs/mall/entity/MallTeamLeader.java | 49 src/main/java/cc/mrbird/febs/mall/controller/ApiLoginController.java | 36 src/main/java/cc/mrbird/febs/mall/dto/ApiXcxLoginDto.java | 12 src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallTeamLeaderServiceImpl.java | 79 src/main/java/cc/mrbird/febs/common/utils/HttpCurlUtil.java | 138 + src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java | 5 src/main/java/cc/mrbird/febs/mall/entity/MallMember.java | 10 src/main/java/cc/mrbird/febs/common/utils/AppContants.java | 5 src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayService.java | 55 src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayComService.java | 34 src/main/java/cc/mrbird/febs/common/utils/SpringContextHolder.java | 66 src/main/java/cc/mrbird/febs/mall/dto/AdminLeaderUpdateDto.java | 16 src/main/java/cc/mrbird/febs/mall/mapper/MallTeamLeaderMapper.java | 30 src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java | 23 src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderInfoVo.java | 39 src/main/java/cc/mrbird/febs/pay/model/JsApiPayResData.java | 232 ++ 93 files changed, 5,861 insertions(+), 28 deletions(-) diff --git a/pom.xml b/pom.xml index cef71ae..782a844 100644 --- a/pom.xml +++ b/pom.xml @@ -39,6 +39,17 @@ <version>${hutool.version}</version> </dependency> + <dependency> + <groupId>commons-httpclient</groupId> + <artifactId>commons-httpclient</artifactId> + <version>3.1</version> + </dependency> + <dependency> + <groupId>com.thoughtworks.xstream</groupId> + <artifactId>xstream</artifactId> + <version>1.4.11.1</version> + </dependency> + <!-- Spring系列 --> <dependency> <groupId>org.springframework.boot</groupId> diff --git a/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java b/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java index bde2591..12a9e75 100644 --- a/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java +++ b/src/main/java/cc/mrbird/febs/common/configure/WebMvcConfigure.java @@ -24,5 +24,7 @@ registration.excludePathPatterns("/api/pay/**"); registration.excludePathPatterns("/api/news/**"); registration.excludePathPatterns("/api/member/cashOutSetting"); + registration.excludePathPatterns("/api/leader/leaderList"); + registration.excludePathPatterns("/api/leader/leaderTitle"); } } diff --git a/src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java b/src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java new file mode 100644 index 0000000..a737ad7 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/common/properties/XcxProperties.java @@ -0,0 +1,22 @@ +package cc.mrbird.febs.common.properties; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +@Data +@Configuration +@ConfigurationProperties(prefix = "xcx") +public class XcxProperties { + + private String wecharLoginUrl; + + private String xcxAppid; + + private String xcxSecret; + + private String wecharPaynotifyUrl; + //测试支付的开关,true:支付0.01元 + private Boolean debug; + +} diff --git a/src/main/java/cc/mrbird/febs/common/utils/AppContants.java b/src/main/java/cc/mrbird/febs/common/utils/AppContants.java index 79d69c3..43d6356 100644 --- a/src/main/java/cc/mrbird/febs/common/utils/AppContants.java +++ b/src/main/java/cc/mrbird/febs/common/utils/AppContants.java @@ -18,6 +18,9 @@ */ public static final String APP_LOGIN_PREFIX = "app_"; + public static final String XCX_LOGIN_PREFIX = "xcx_"; + public static final String XCX_LOGIN_PHONE_PREFIX = "xcx_p"; + public static final String PC_LOGIN_PREFIX = "pc_"; /** @@ -68,4 +71,6 @@ public static final String AGENT_LEVEL = "AGENT_LEVEL"; public static final String AGENT_LEVEL_REQUIRE = "AGENT_LEVEL_REQUIRE"; + public static final String SIGN_MD5 = "MD5"; + } diff --git a/src/main/java/cc/mrbird/febs/common/utils/HttpCurlUtil.java b/src/main/java/cc/mrbird/febs/common/utils/HttpCurlUtil.java new file mode 100644 index 0000000..eb43584 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/common/utils/HttpCurlUtil.java @@ -0,0 +1,138 @@ +package cc.mrbird.febs.common.utils; + +import org.apache.commons.httpclient.HttpClient; +import org.apache.commons.httpclient.HttpException; +import org.apache.commons.httpclient.methods.GetMethod; +import org.apache.commons.httpclient.methods.PostMethod; +import org.apache.commons.httpclient.methods.RequestEntity; +import org.apache.commons.httpclient.methods.StringRequestEntity; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Map; + +public class HttpCurlUtil { + + + /** + * 向指定URL发送POST方法的请求 + * + * @param url 发送请求的URL + * @param data 请求参数,请求参数应该是json格式。 + */ + public static String sendPostHttp(String url, String data) throws HttpException, IOException { + + HttpClient httpClient = new HttpClient(); + PostMethod post = new PostMethod(url); + post.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); + post.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36"); + post.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + post.setRequestHeader("Connection", "keep-alive"); + RequestEntity entity = new StringRequestEntity(data, "text/html", "utf-8"); + post.setRequestEntity(entity); + httpClient.executeMethod(post); + + return post.getResponseBodyAsString(); + } + + /** + * 向指定URL发送get方法的请求 + * + * @param url 发送请求的URL + * @param data 请求参数,请求参数应该是json格式。 + */ + public static String sendGetHttp(String url, Map<String, String> params) throws HttpException, IOException { + if (params != null) { + StringBuffer param = new StringBuffer(); + int i = 0; + for (String key : params.keySet()) { + if (i == 0) + param.append("?"); + else + param.append("&"); + param.append(key).append("=").append((String) params.get(key)); + i++; + } + url = url + param; + } + HttpClient httpClient = new HttpClient(); + GetMethod method = new GetMethod(url); + method.setRequestHeader("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"); + method.setRequestHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36"); + method.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); + method.setRequestHeader("Connection", "keep-alive"); + httpClient.executeMethod(method); + return method.getResponseBodyAsString(); + } + + /** + * 向指定URL发送POST请求 + * @param url 请求路径 + * @param params 请求参数 + * @return + */ + public static String sendPost(String url, Map<String, String> params) { + OutputStreamWriter out = null; + BufferedReader in = null; + StringBuilder result = new StringBuilder(); + try { + URL realUrl = new URL(url); + HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); + // 发送POST请求必须设置如下两行 + conn.setDoOutput(true); + conn.setDoInput(true); + // POST方法 + conn.setRequestMethod("POST"); + // 设置通用的请求属性 + conn.setRequestProperty("accept", "*/*"); + conn.setRequestProperty("connection", "Keep-Alive"); + conn.setRequestProperty("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1;SV1)"); + conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); + conn.connect(); + // 获取URLConnection对象对应的输出流 + out = new OutputStreamWriter(conn.getOutputStream(), "UTF-8"); + // 发送请求参数 + if (params != null) { + StringBuilder param = new StringBuilder(); + for (Map.Entry<String, String> entry : params.entrySet()) { + if (param.length() > 0) { + param.append("&"); + } + param.append(entry.getKey()); + param.append("="); + param.append(entry.getValue()); + } + out.write(param.toString()); + } + // flush输出流的缓冲 + out.flush(); + // 定义BufferedReader输入流来读取URL的响应 + in = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8")); + String line; + while ((line = in.readLine()) != null) { + result.append(line); + } + } catch (Exception e) { + e.printStackTrace(); + } + //使用finally块来关闭输出流、输入流 + finally { + try { + if (out != null) { + out.close(); + } + if (in != null) { + in.close(); + } + } catch (IOException ex) { + ex.printStackTrace(); + } + } + return result.toString(); + } + +} diff --git a/src/main/java/cc/mrbird/febs/common/utils/SpringContextHolder.java b/src/main/java/cc/mrbird/febs/common/utils/SpringContextHolder.java new file mode 100644 index 0000000..82b7a1d --- /dev/null +++ b/src/main/java/cc/mrbird/febs/common/utils/SpringContextHolder.java @@ -0,0 +1,66 @@ +package cc.mrbird.febs.common.utils; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.DisposableBean; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +/** + * @Author wzy + * @Date 2020/5/11 + * @email wangdoubleone@gmail.com + * @Version V1.0 + **/ +@Slf4j +@Component +public class SpringContextHolder implements ApplicationContextAware, DisposableBean { + + private static ApplicationContext applicationContext = null; + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + @SuppressWarnings("unchecked") + public static <T> T getBean(String name) { + assertContextInjected(); + return (T) applicationContext.getBean(name); + } + + /** + * 从静态变量applicationContext中取得Bean, 自动转型为所赋值对象的类型. + */ + public static <T> T getBean(Class<T> requiredType) { + assertContextInjected(); + return applicationContext.getBean(requiredType); + } + + private static void assertContextInjected() { + if (applicationContext == null) { + throw new IllegalStateException("applicaitonContext属性未注入, 请在applicationContext" + + ".xml中定义SpringContextHolder或在SpringBoot启动类中注册SpringContextHolder."); + } + } + + /** + * 检查ApplicationContext不为空. + */ + private static void clearHolder() { + log.debug("清除SpringContextHolder中的ApplicationContext:" + applicationContext); + applicationContext = null; + } + + @Override + public void destroy() throws Exception { + SpringContextHolder.clearHolder(); + } + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (SpringContextHolder.applicationContext != null) { + log.warn("SpringContextHolder中的ApplicationContext被覆盖, 原有ApplicationContext为:" + SpringContextHolder.applicationContext); + } + SpringContextHolder.applicationContext = applicationContext; + } +} diff --git a/src/main/java/cc/mrbird/febs/mall/controller/AdminGroupController.java b/src/main/java/cc/mrbird/febs/mall/controller/AdminGroupController.java new file mode 100644 index 0000000..0728ecf --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/controller/AdminGroupController.java @@ -0,0 +1,20 @@ +package cc.mrbird.febs.mall.controller; + +import cc.mrbird.febs.common.controller.BaseController; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Map; + +@Slf4j +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/admin/group") +public class AdminGroupController extends BaseController { + + +} diff --git a/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java index fdc382f..b5aa7ad 100644 --- a/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java +++ b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallOrderController.java @@ -281,6 +281,63 @@ return null; } + @GetMapping("exportOrderListOne") + @ControllerEndpoint(operation = "订单列表", exceptionMessage = "导出失败") + public FebsResponse exportOrderListOne(MallOrderInfo mallOrderInfo, HttpServletResponse response) throws IOException { + + List<ExcelSheetPO> res = new ArrayList<>(); + ExcelSheetPO orderSheet = new ExcelSheetPO(); + String title = "订单列表"; + orderSheet.setSheetName(title); + orderSheet.setTitle(title); + String[] header = {"订单编号", "订单金额", "下单时间", "配送方式", "收货姓名", "收货电话", "商品名称", "团长名称", "团长手机号码", "自提点名称","详细地址"}; + orderSheet.setHeaders(header); + + QueryRequest request = new QueryRequest(); + request.setPageNum(1); + request.setPageSize(9999); + List<MallOrderInfo> dataList = adminMallOrderService.findOrderListInPage(mallOrderInfo, request).getRecords(); + List<List<Object>> list = new ArrayList<>(); + if (dataList.size() > 0) { + for (MallOrderInfo item : dataList) { + List<Object> temp = new ArrayList<>(); + temp.add(item.getOrderNo()); + temp.add(item.getAmount()); + temp.add(DateUtil.format(item.getOrderTime(), "yyyy-MM-dd HH:mm:ss")); + temp.add("自提"); + temp.add(item.getName()); + temp.add(item.getPhone()); + if (CollUtil.isNotEmpty(item.getItems())) { + StringBuilder sb = new StringBuilder(); + + for (MallOrderItem itemItem : item.getItems()) { + if (StrUtil.isNotBlank(sb)) { + sb.append(";" + itemItem.getGoodsName() + "*" + itemItem.getCnt()); + } else { + sb.append(itemItem.getGoodsName() + "*" + itemItem.getCnt()); + } + } + temp.add(sb.toString()); + } else { + temp.add(""); + } + temp.add(item.getLeaderName()); + temp.add(item.getLeaderPhone()); + temp.add(item.getAddressArea()); + temp.add(item.getProvince()+item.getCity()+item.getTownship()+item.getDetailAddress()); + list.add(temp); + } + } + orderSheet.setDataList(list); + res.add(orderSheet); + response = ResponseHeadUtil.setExcelHead(response); + response.setHeader("Content-Disposition", + "attachment;filename=" + URLEncoder.encode(title + DateUtil.format(new Date(), "yyyyMMDDHHmmss") + ".xlsx".trim(), "UTF-8")); + OutputStream os = response.getOutputStream(); + ExcelUtil.createWorkbookAtOutStream(ExcelVersion.V2007, res, os, true); + return null; + } + @PostMapping(value = "/importDeliver") @ControllerEndpoint(operation = "导入发货", exceptionMessage = "导入失败") public FebsResponse importDeliver(@RequestBody MultipartFile file) throws IOException { diff --git a/src/main/java/cc/mrbird/febs/mall/controller/AdminMallTeamLeaderController.java b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallTeamLeaderController.java new file mode 100644 index 0000000..f1135fc --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/controller/AdminMallTeamLeaderController.java @@ -0,0 +1,60 @@ +package cc.mrbird.febs.mall.controller; + +import cc.mrbird.febs.common.annotation.ControllerEndpoint; +import cc.mrbird.febs.common.controller.BaseController; +import cc.mrbird.febs.common.entity.FebsResponse; +import cc.mrbird.febs.common.entity.QueryRequest; +import cc.mrbird.febs.mall.dto.AdminLeaderUpdateDto; +import cc.mrbird.febs.mall.entity.MallGoodsCategory; +import cc.mrbird.febs.mall.entity.MallTeamLeader; +import cc.mrbird.febs.mall.service.IAdminMallTeamLeaderService; +import cc.mrbird.febs.mall.vo.AdminSelectListLeaderVo; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.validation.Valid; +import java.util.List; +import java.util.Map; + +@Slf4j +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/admin/leader") +public class AdminMallTeamLeaderController extends BaseController { + + + private final IAdminMallTeamLeaderService iAdminMallTeamLeaderService; + + /** + * 团长信息--列表 + */ + @GetMapping("leaderList") + public FebsResponse getLeaderList(MallTeamLeader mallTeamLeader, QueryRequest request) { + Map<String, Object> data = getDataTable(iAdminMallTeamLeaderService.getLeaderListInPage(mallTeamLeader, request)); + return new FebsResponse().success().data(data); + } + + /** + * 团长信息--审核 + */ + @PostMapping("leaderUpdate") + @ControllerEndpoint(operation = "团长信息--审核", exceptionMessage = "审核失败") + public FebsResponse leaderUpdate(@Valid AdminLeaderUpdateDto adminLeaderUpdateDto) { + return iAdminMallTeamLeaderService.leaderUpdate(adminLeaderUpdateDto); + } + + /** + * 团长信息--下拉列表 + */ + @GetMapping("selectList") + public List<AdminSelectListLeaderVo> selectList(MallTeamLeader mallTeamLeader) { + return iAdminMallTeamLeaderService.selectList(mallTeamLeader); + } + +} diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ApiLoginController.java b/src/main/java/cc/mrbird/febs/mall/controller/ApiLoginController.java index 8f6c8f3..145379b 100644 --- a/src/main/java/cc/mrbird/febs/mall/controller/ApiLoginController.java +++ b/src/main/java/cc/mrbird/febs/mall/controller/ApiLoginController.java @@ -1,19 +1,19 @@ package cc.mrbird.febs.mall.controller; import cc.mrbird.febs.common.entity.FebsResponse; -import cc.mrbird.febs.mall.dto.ForgetPwdDto; -import cc.mrbird.febs.mall.dto.LoginDto; -import cc.mrbird.febs.mall.dto.RegisterAppealDto; -import cc.mrbird.febs.mall.dto.RegisterDto; +import cc.mrbird.febs.mall.dto.*; import cc.mrbird.febs.mall.service.IApiMallMemberService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import net.sf.json.JSONObject; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.validation.Valid; +import java.io.IOException; +import java.util.Dictionary; /** * @author wzy @@ -55,4 +55,32 @@ memberService.addRegisterAppeal(registerAppeal); return new FebsResponse().success().message("申请成功"); } + + /** + * 小程序登录 + */ + @ApiOperation(value = "小程序登录", notes = "小程序登录") + @PostMapping(value = "/xcxLogin") + public FebsResponse xcxLogin(@RequestBody ApiXcxLoginDto apiXcxLoginDto) throws IOException { + return memberService.xcxLogin(apiXcxLoginDto); + } + + /** + * 小程序手机号登录 + */ + @ApiOperation(value = "小程序手机号登录", notes = "小程序手机号登录") + @PostMapping(value = "/xcxPhoneLogin") + public FebsResponse xcxPhoneLogin(@RequestBody ApiXcxPhoneLoginDto apiXcxPhoneLoginDto){ + return memberService.xcxPhoneLogin(apiXcxPhoneLoginDto); + } + + /** + * 小程序接收用户数据,更新用户信息 + */ + @ApiOperation(value = "小程序接收用户数据", notes = "小程序接收用户数据") + @PostMapping(value = "/xcxSaveInfo") + public FebsResponse xcxSaveInfo(@RequestBody ApiXcxSaveInfoDto apiXcxSaveInfoDto){ + return memberService.xcxSaveInfo(apiXcxSaveInfoDto); + } + } diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java index ef31935..034e190 100644 --- a/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java +++ b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallMemberController.java @@ -35,6 +35,15 @@ private final IMallMemberWithdrawService mallMemberWithdrawService; private final IApiMallMemberWalletService walletService; + /** + * 小程序接收用户数据,更新用户信息 + */ + @ApiOperation(value = "小程序接收用户数据", notes = "小程序接收用户数据") + @PostMapping(value = "/xcxSaveInfo") + public FebsResponse xcxSaveInfo(@RequestBody ApiXcxSaveInfoDto apiXcxSaveInfoDto){ + return memberService.xcxSaveInfo(apiXcxSaveInfoDto); + } + @ApiOperation(value = "获取商城用户信息", notes = "获取商城用户信息") @ApiResponses({ @ApiResponse(code = 200, message = "success", response = MallMemberVo.class) diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ApiMallTeamLeaderController.java b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallTeamLeaderController.java new file mode 100644 index 0000000..d1a84d3 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/controller/ApiMallTeamLeaderController.java @@ -0,0 +1,115 @@ +package cc.mrbird.febs.mall.controller; + +import cc.mrbird.febs.common.annotation.ControllerEndpoint; +import cc.mrbird.febs.common.entity.FebsResponse; +import cc.mrbird.febs.mall.dto.*; +import cc.mrbird.febs.mall.service.IApiMallTeamLeaderService; +import cc.mrbird.febs.mall.vo.ApiLeaderInfoVo; +import cc.mrbird.febs.mall.vo.ApiLeaderListVo; +import cc.mrbird.febs.mall.vo.ApiMallleaderStateVo; +import cc.mrbird.febs.mall.vo.OrderListVo; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import javax.validation.Valid; + +@Slf4j +@Validated +@RestController +@RequiredArgsConstructor +@RequestMapping(value = "/api/leader") +@Api(value = "ApiMallTeamLeaderController", tags = "团长接口类") +public class ApiMallTeamLeaderController { + + private final IApiMallTeamLeaderService iApiMallTeamLeaderService; + + /** + * 申请团长 + */ + @ApiOperation(value = "申请团长", notes = "申请团长") + @PostMapping(value = "/applyLeader") + public FebsResponse applyLeader(@RequestBody @Valid ApiApplayLeaderDto apiApplayLeaderDto) { + return iApiMallTeamLeaderService.applyLeader(apiApplayLeaderDto); + } + + /** + * 团长列表 + */ + @ApiOperation(value = "团长列表", notes = "团长列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "success", response = ApiLeaderListVo.class) + }) + @PostMapping(value = "/leaderList") + public FebsResponse leaderList(@RequestBody @Valid ApiLeaderListDto apiLeaderListDto) { + return new FebsResponse().success().data(iApiMallTeamLeaderService.findLeaderListInPage(apiLeaderListDto)); + } + + /** + *是否允许申请团长 + */ + @ApiOperation(value = "是否允许申请团长", notes = "是否允许申请团长") + @ApiResponses({ + @ApiResponse(code = 200, message = "success", response = ApiMallleaderStateVo.class) + }) + @GetMapping(value = "/leaderState") + public FebsResponse leaderState() { + return iApiMallTeamLeaderService.leaderState(); + } + + + /** + *选择团长 + */ + @ApiOperation(value = "选择团长", notes = "选择团长") + @ApiResponses({ + @ApiResponse(code = 200, message = "success", response = ApiLeaderInfoVo.class) + }) + @GetMapping(value = "/leaderChoose/{id}") + public FebsResponse leaderChoose(@PathVariable(value = "id") Long id) { + return iApiMallTeamLeaderService.getApiLeaderInfoVoById(id); + } + + /** + * 团长查看自提点订单列表 + */ + @ApiOperation(value = "团长查看自提点订单列表", notes = "团长查看自提点订单列表") + @ApiResponses({ + @ApiResponse(code = 200, message = "success", response = OrderListVo.class) + }) + @PostMapping(value = "/leaderOrderList") + public FebsResponse leaderOrderList(@RequestBody ApiLeaderOrderListDto apiLeaderOrderListDto) { + return new FebsResponse().success().data(iApiMallTeamLeaderService.findLeaderOrderListInPage(apiLeaderOrderListDto)); + } + + /** + * 团长点击到货确认,订单从状态 2 变更到状态 3 ,即待提货 + */ + @ApiOperation(value = "团长点击到货确认,订单从状态 2 变更到状态 3 ,即待提货", notes = "团长点击到货确认,订单从状态 2 变更到状态 3 ,即待提货") + @PostMapping("/leaderOrderConfirm") + public FebsResponse leaderOrderConfirm(@Valid ApiLeaderOrderConfirmDto apiLeaderOrderConfirmDto) { + return iApiMallTeamLeaderService.leaderOrderConfirm(apiLeaderOrderConfirmDto); + } + + /** + * 商品列表页的团长信息 + * 有团长特征码直接显示该团长, + * 有经纬度,按照经纬度选择距离最近的 + * 没有选择团长列表的第一个 + */ + @ApiOperation(value = "商品列表页的团长信息", notes = "商品列表页的团长信息") + @ApiResponses({ + @ApiResponse(code = 200, message = "success", response = ApiLeaderInfoVo.class) + }) + @PostMapping("/leaderTitle") + public FebsResponse leaderTitle(@RequestBody ApiLeaderTitleDto apiLeaderTitleDto) { + return iApiMallTeamLeaderService.leaderTitle(apiLeaderTitleDto); + } + + +} diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ViewGroupController.java b/src/main/java/cc/mrbird/febs/mall/controller/ViewGroupController.java new file mode 100644 index 0000000..36f5f24 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/controller/ViewGroupController.java @@ -0,0 +1,13 @@ +package cc.mrbird.febs.mall.controller; + +import cc.mrbird.febs.common.controller.BaseController; +import cc.mrbird.febs.common.entity.FebsConstant; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller("groupView") +@RequestMapping(FebsConstant.VIEW_PREFIX + "modules/group") +@RequiredArgsConstructor +public class ViewGroupController extends BaseController { +} diff --git a/src/main/java/cc/mrbird/febs/mall/controller/ViewMallTeamLeaderController.java b/src/main/java/cc/mrbird/febs/mall/controller/ViewMallTeamLeaderController.java new file mode 100644 index 0000000..dcc8b26 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/controller/ViewMallTeamLeaderController.java @@ -0,0 +1,44 @@ +package cc.mrbird.febs.mall.controller; + +import cc.mrbird.febs.common.controller.BaseController; +import cc.mrbird.febs.common.entity.FebsConstant; +import cc.mrbird.febs.common.utils.FebsUtil; +import cc.mrbird.febs.mall.service.IAdminMallOrderService; +import cc.mrbird.febs.mall.service.IAdminMallTeamLeaderService; +import cc.mrbird.febs.mall.vo.AdminMallOrderVo; +import cc.mrbird.febs.mall.vo.AdminMallTeamLeaderVo; +import lombok.RequiredArgsConstructor; +import org.apache.shiro.authz.annotation.RequiresPermissions; +import org.springframework.stereotype.Controller; +import org.springframework.ui.Model; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestMapping; + +@Controller("leaderView") +@RequestMapping(FebsConstant.VIEW_PREFIX + "modules/leader") +@RequiredArgsConstructor +public class ViewMallTeamLeaderController extends BaseController { + + private final IAdminMallTeamLeaderService iAdminMallTeamLeaderService; + + /** + * 团长信息--列表 + */ + @GetMapping("leaderList") + @RequiresPermissions("leaderList:view") + public String leaderList() { + return FebsUtil.view("modules/leader/leaderList"); + } + + /** + * 团长信息-审核 + */ + @GetMapping("leaderUpdate/{id}") + @RequiresPermissions("leaderUpdate:update") + public String leaderUpdate(@PathVariable long id, Model model) { + AdminMallTeamLeaderVo data = iAdminMallTeamLeaderService.getMallTeamLederInfoById(id); + model.addAttribute("leaderInfo", data); + return FebsUtil.view("modules/leader/leaderUpdate"); + } +} diff --git a/src/main/java/cc/mrbird/febs/mall/conversion/MallTeamLeaderConversion.java b/src/main/java/cc/mrbird/febs/mall/conversion/MallTeamLeaderConversion.java new file mode 100644 index 0000000..c05bffa --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/conversion/MallTeamLeaderConversion.java @@ -0,0 +1,26 @@ +package cc.mrbird.febs.mall.conversion; + +import cc.mrbird.febs.mall.dto.ApiApplayLeaderDto; +import cc.mrbird.febs.mall.entity.MallTeamLeader; +import cc.mrbird.febs.mall.vo.AdminMallTeamLeaderVo; +import cc.mrbird.febs.mall.vo.ApiLeaderInfoVo; +import cc.mrbird.febs.mall.vo.ApiLeaderListVo; +import cc.mrbird.febs.mall.vo.OrderDetailVo; +import org.mapstruct.Mapper; +import org.mapstruct.factory.Mappers; + +import java.util.List; + +@Mapper +public abstract class MallTeamLeaderConversion { + + public static final MallTeamLeaderConversion INSTANCE = Mappers.getMapper(MallTeamLeaderConversion.class); + + public abstract MallTeamLeader dtoToEntity(ApiApplayLeaderDto apiApplayLeaderDto); + + public abstract List<ApiLeaderListVo> entitysToVos(List<MallTeamLeader> mallTeamLeaders); + + public abstract AdminMallTeamLeaderVo entityToVo(MallTeamLeader mallTeamLeaders); + + +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/AddOrderDto.java b/src/main/java/cc/mrbird/febs/mall/dto/AddOrderDto.java index 11d73f6..0b7e21c 100644 --- a/src/main/java/cc/mrbird/febs/mall/dto/AddOrderDto.java +++ b/src/main/java/cc/mrbird/febs/mall/dto/AddOrderDto.java @@ -19,6 +19,12 @@ @ApiModelProperty(value = "地址ID", example = "1") private Long addressId; + @ApiModelProperty(value = "提货团长特征码", example = "1") + private String takeUniqueCode; + +// @ApiModelProperty(value = "配送方式 1:自提 2:快递(默认自提)", example = "1") +// private Integer deliveryType; + @ApiModelProperty(value = "订单提交类型", example = "1从购物车提交, 2从商品直接提交") private Integer type; diff --git a/src/main/java/cc/mrbird/febs/mall/dto/AdminLeaderUpdateDto.java b/src/main/java/cc/mrbird/febs/mall/dto/AdminLeaderUpdateDto.java new file mode 100644 index 0000000..1daf80b --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/AdminLeaderUpdateDto.java @@ -0,0 +1,16 @@ +package cc.mrbird.febs.mall.dto; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import javax.validation.constraints.NotNull; +@Data +@ApiModel(value = "AdminLeaderUpdateDto", description = "接收参数类") +public class AdminLeaderUpdateDto { + + @NotNull(message = "ID不能为空") + private Long id; + + @NotNull(message = "审核结果不能为空") + private int isOk; +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiApplayLeaderDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiApplayLeaderDto.java new file mode 100644 index 0000000..33eeaae --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiApplayLeaderDto.java @@ -0,0 +1,53 @@ +package cc.mrbird.febs.mall.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +@ApiModel(value = "ApiApplayLeaderDto", description = "参数接收类") +public class ApiApplayLeaderDto { + + //团长姓名 + @NotBlank(message = "姓名不能为空") + @ApiModelProperty(value = "团长姓名") + private String name; + //手机号码 + @NotBlank(message = "手机号码不能为空") + @ApiModelProperty(value = "手机号码") + private String phone; + //自提点照片 + @NotBlank(message = "自提点照片不能为空") + @ApiModelProperty(value = "自提点照片") + private String addressPic; + //省 + @NotBlank(message = "省不能为空") + @ApiModelProperty(value = "省") + private String province; + //市 + @NotBlank(message = "市不能为空") + @ApiModelProperty(value = "市") + private String city; + //区 + @NotBlank(message = "区不能为空") + @ApiModelProperty(value = "区") + private String township; + //小区名称 + @NotBlank(message = "小区名称(自提点名称)不能为空") + @ApiModelProperty(value = "小区名称(自提点名称)") + private String addressArea; + //详细地址 + @NotBlank(message = "详细地址不能为空") + @ApiModelProperty(value = "详细地址") + private String detailAddress; + //经度 + @NotBlank(message = "经度不能为空") + @ApiModelProperty(value = "经度") + private Double longitude; + //纬度 + @NotBlank(message = "纬度不能为空") + @ApiModelProperty(value = "纬度") + private Double latitude; +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderListDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderListDto.java new file mode 100644 index 0000000..4a902e8 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderListDto.java @@ -0,0 +1,31 @@ +package cc.mrbird.febs.mall.dto; + + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +@ApiModel(value = "ApiLeaderListDto", description = "参数接收类") +public class ApiLeaderListDto { + + @ApiModelProperty(value = "第几页", example = "1") + private Integer pageNum; + + @ApiModelProperty(value = "每页数量", example = "10") + private Integer pageSize; + + @ApiModelProperty(value = "团长姓名,电话,自提地址", example = "123") + private String query; + + @ApiModelProperty(value = "经度", example = "123") + @NotNull(message = "请选择您的地址") + private Double longitude; + + @ApiModelProperty(value = "纬度", example = "123") + @NotNull(message = "请选择您的地址") + private Double latitude; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderConfirmDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderConfirmDto.java new file mode 100644 index 0000000..6381ee3 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderConfirmDto.java @@ -0,0 +1,15 @@ +package cc.mrbird.febs.mall.dto; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +@Data +@ApiModel(value = "ApiLeaderOrderConfirmDto", description = "参数接收类") +public class ApiLeaderOrderConfirmDto { + + @NotBlank(message = "订单编号不能为空") + private String orderNo; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderListDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderListDto.java new file mode 100644 index 0000000..9f998f3 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderOrderListDto.java @@ -0,0 +1,29 @@ +package cc.mrbird.febs.mall.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(value = "ApiLeaderOrderListDto", description = "参数接收类") +public class ApiLeaderOrderListDto { + + @ApiModelProperty(value = "一页数量", example = "10") + private Integer pageSize; + + @ApiModelProperty(value = "第几页", example = "1") + private Integer pageNum; + + @ApiModelProperty(value = "搜索参数(姓名,电话,提货码)", example = "1") + private String query; + + @ApiModelProperty(value = "订单状态", example = "0-全部 1-待付款 2-待发货(待确认) 3-待收货(待提货) 4-已完成 5-已取消") + private Integer status; + + @ApiModelProperty(hidden = true) + private Long memberId; + + @ApiModelProperty(value = "1-普通订单, 2-积分订单", example = "1") + private Integer orderType; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderTitleDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderTitleDto.java new file mode 100644 index 0000000..448564a --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiLeaderTitleDto.java @@ -0,0 +1,22 @@ +package cc.mrbird.febs.mall.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Data +@ApiModel(value = "ApiLeaderTitleDto", description = "参数接收类") +public class ApiLeaderTitleDto { + + @ApiModelProperty(value = "团长特征码", example = "1") + private String uniqueCode; + + @ApiModelProperty(value = "经度", example = "123") + private Double longitude; + + @ApiModelProperty(value = "纬度", example = "123") + private Double latitude; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxLoginDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxLoginDto.java new file mode 100644 index 0000000..0156599 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxLoginDto.java @@ -0,0 +1,12 @@ +package cc.mrbird.febs.mall.dto; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +@Data +@ApiModel(value = "ApiXcxLoginDto", description = "小程序登录") +public class ApiXcxLoginDto { + + private String code; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxPhoneLoginDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxPhoneLoginDto.java new file mode 100644 index 0000000..a141a2e --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxPhoneLoginDto.java @@ -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 = "ApiXcxPhoneLoginDto", description = "小程序登录") +public class ApiXcxPhoneLoginDto { + + @ApiModelProperty(value = "手机号" ) + private String phone; + + @ApiModelProperty(value = "验证码" ) + private String code; +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java new file mode 100644 index 0000000..e7df061 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/dto/ApiXcxSaveInfoDto.java @@ -0,0 +1,23 @@ +package cc.mrbird.febs.mall.dto; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(value = "ApiXcxSaveInfoDto", description = "小程序接收用户数据") +public class ApiXcxSaveInfoDto { + + @ApiModelProperty(value = "手机号码" ) + private String phone; + + @ApiModelProperty(value = "昵称" ) + private String nickName; + + @ApiModelProperty(value = "头像" ) + private String avatarUrl; + + @ApiModelProperty(value = "性别" ) + private Integer gender; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/dto/MallOrderInfoDto.java b/src/main/java/cc/mrbird/febs/mall/dto/MallOrderInfoDto.java index 9c40105..1c580f3 100644 --- a/src/main/java/cc/mrbird/febs/mall/dto/MallOrderInfoDto.java +++ b/src/main/java/cc/mrbird/febs/mall/dto/MallOrderInfoDto.java @@ -24,4 +24,8 @@ private String name; private Integer orderType; + //配送方式 1:自提 2:快递 + private Integer deliveryType; + + private String uniqueCode; } diff --git a/src/main/java/cc/mrbird/febs/mall/dto/OrderListDto.java b/src/main/java/cc/mrbird/febs/mall/dto/OrderListDto.java index 7a900a0..054cbb5 100644 --- a/src/main/java/cc/mrbird/febs/mall/dto/OrderListDto.java +++ b/src/main/java/cc/mrbird/febs/mall/dto/OrderListDto.java @@ -18,10 +18,10 @@ @ApiModelProperty(value = "第几页", example = "1") private Integer pageNum; - @ApiModelProperty(value = "搜索参数", example = "1") + @ApiModelProperty(value = "搜索参数(姓名,电话,提货码)", example = "1") private String query; - @ApiModelProperty(value = "订单状态", example = "0-全部 1-待付款 2-待发货 3-待收货 4-已完成 5-已取消") + @ApiModelProperty(value = "订单状态", example = "0-全部 1-待付款 2-待发货(待确认) 3-待收货(待提货) 4-已完成 5-已取消") private Integer status; @ApiModelProperty(hidden = true) diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallGroup.java b/src/main/java/cc/mrbird/febs/mall/entity/MallGroup.java new file mode 100644 index 0000000..963e9b4 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/entity/MallGroup.java @@ -0,0 +1,29 @@ +package cc.mrbird.febs.mall.entity; + +import cc.mrbird.febs.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +@Data +@TableName("mall_group") +public class MallGroup extends BaseEntity { + + //商品Id + private Long goodsId; + //平团是否成功 1:进行中 2:平团成功 3:已取消 + private Integer groupState; + //开团时间 + private Date beginTime; + //最晚结束时间 + private Date endTime; + //拼团价格 + private String groupPrice; + //拼团成功要求人数 + private Integer groupTeamNum; + //团长ID + private Long headMemberId; + + +} diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallGroupJoinMember.java b/src/main/java/cc/mrbird/febs/mall/entity/MallGroupJoinMember.java new file mode 100644 index 0000000..b8c44a0 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/entity/MallGroupJoinMember.java @@ -0,0 +1,25 @@ +package cc.mrbird.febs.mall.entity; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +@Data +@TableName("mall_group_join_member") +public class MallGroupJoinMember { + + //团购信息表ID + private Long groupId; + //订单ID + private Long orderId; + //是否已支付 1-是 2-否 + private Long isHasPay; + //支付结束时间 + private Date payEndTime; + //是否已取消 1-是 2-否 + private Long isHasCancel; + //用户ID + private Long memberId; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java b/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java index 61a5590..3775ecf 100644 --- a/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java +++ b/src/main/java/cc/mrbird/febs/mall/entity/MallMember.java @@ -134,4 +134,14 @@ */ private Integer storeMaster; + /** + * 微信用户标识 + */ + private String openId; + + /** + * 会话密钥 + */ + private String sessionKey; + } diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java b/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java index eb7f24a..72b0f24 100644 --- a/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java +++ b/src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java @@ -3,6 +3,7 @@ import cc.mrbird.febs.common.entity.BaseEntity; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; import java.math.BigDecimal; @@ -87,4 +88,37 @@ */ public static final Integer COMMENT_STATE_NO = 1; public static final Integer COMMENT_STATE_YES = 2; + + //提货团长特征码 + private String takeUniqueCode; + //提货码 + private String takeCode; + //配送方式 1:自提 2:快递 + private Integer deliveryType; + + /** + * 自提点信息 + */ + @TableField(exist = false) + private String leaderName; + @TableField(exist = false) + private String leaderPhone; + @TableField(exist = false) + private String addressPic; + @TableField(exist = false) + private String province; + @TableField(exist = false) + private String city; + @TableField(exist = false) + private String township; + @TableField(exist = false) + private String addressArea; + @TableField(exist = false) + private String detailAddress; + + + /** + * 微信订单编号 + */ + private String wxOrderNo; } diff --git a/src/main/java/cc/mrbird/febs/mall/entity/MallTeamLeader.java b/src/main/java/cc/mrbird/febs/mall/entity/MallTeamLeader.java new file mode 100644 index 0000000..a91d2aa --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/entity/MallTeamLeader.java @@ -0,0 +1,49 @@ +package cc.mrbird.febs.mall.entity; + + +import cc.mrbird.febs.common.entity.BaseEntity; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.util.Date; + +//团长信息表 +@Data +@TableName("mall_team_leader") +public class MallTeamLeader extends BaseEntity { + + //用户ID + private Long memberId; + //申请状态 1:审核通过 2:审核不通过 3:申请中 + private Integer state; + public static final Integer STATE_YES = 1; + public static final Integer STATE_NO = 2; + public static final Integer STATE_ING = 3; + //团长姓名 + private String name; + //手机号码 + private String phone; + //团长特征码 + private String uniqueCode; + //自提点照片 + private String addressPic; + //省 + private String province; + //市 + private String city; + //区 + private String township; + //小区名称 + private String addressArea; + //详细地址 + private String detailAddress; + //经度 + private Double longitude; + //纬度 + private Double latitude; + + @TableField(exist = false) + private Double distance; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/mapper/MallGroupMapper.java b/src/main/java/cc/mrbird/febs/mall/mapper/MallGroupMapper.java new file mode 100644 index 0000000..048eb27 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/mapper/MallGroupMapper.java @@ -0,0 +1,7 @@ +package cc.mrbird.febs.mall.mapper; + +import cc.mrbird.febs.mall.entity.MallGroup; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +public interface MallGroupMapper extends BaseMapper<MallGroup> { +} diff --git a/src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java b/src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java index 5c4787a..8f83a2d 100644 --- a/src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java +++ b/src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java @@ -85,4 +85,6 @@ List<MallMember> selectDirectorsOrStoreMaster(@Param("type") Integer type); List<MallMember> selectMemberWithLevel(String level); + + MallMember selectMemberByOpenId(@Param("openId")String openId); } diff --git a/src/main/java/cc/mrbird/febs/mall/mapper/MallTeamLeaderMapper.java b/src/main/java/cc/mrbird/febs/mall/mapper/MallTeamLeaderMapper.java new file mode 100644 index 0000000..30978b4 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/mapper/MallTeamLeaderMapper.java @@ -0,0 +1,30 @@ +package cc.mrbird.febs.mall.mapper; + +import cc.mrbird.febs.mall.dto.ApiLeaderListDto; +import cc.mrbird.febs.mall.dto.ApiLeaderOrderListDto; +import cc.mrbird.febs.mall.entity.MallOrderInfo; +import cc.mrbird.febs.mall.entity.MallTeamLeader; +import cc.mrbird.febs.mall.vo.AdminMallTeamLeaderVo; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +public interface MallTeamLeaderMapper extends BaseMapper<MallTeamLeader> { + + IPage<AdminMallTeamLeaderVo> selectLeaderListInPage(Page<AdminMallTeamLeaderVo> page, @Param("record")MallTeamLeader mallTeamLeader); + + IPage<MallTeamLeader> selectApiLeaderListInPage(Page<MallTeamLeader> page, @Param("record")ApiLeaderListDto apiLeaderListDto); + + List<MallTeamLeader> selectListByMemberIdAndState(@Param("memberId")Long memberId, @Param("state")Integer stateIng); + + IPage<MallOrderInfo> selectApiLeaderOrderListInPage(IPage<MallOrderInfo> page, @Param("record")ApiLeaderOrderListDto apiLeaderOrderListDto); + + List<MallTeamLeader> getMallTeamLeaderList(); + + MallTeamLeader selectLeaderByUniqueCode(@Param("uniqueCode")String uniqueCode); + + MallTeamLeader selectLeaderByLonAndLat(@Param("longitude")Double longitude, @Param("latitude")Double latitude); +} diff --git a/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java b/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java index c9ca6a6..12beb38 100644 --- a/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java +++ b/src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java @@ -2,6 +2,7 @@ import cc.mrbird.febs.common.enumerates.OrderStatusEnum; import cc.mrbird.febs.mall.entity.MallOrderInfo; +import cc.mrbird.febs.mall.mapper.MallMemberMapper; import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUnit; @@ -25,6 +26,9 @@ @Autowired private MallOrderInfoMapper orderInfoMapper; + @Autowired + private MallMemberMapper mallMemberMapper; + @Scheduled(cron = "0 0/5 * * * ? ") public void overtimeJob() { log.info("订单超时任务执行"); @@ -42,4 +46,11 @@ } } + + @Scheduled(cron = "0/5 * * * * ? ") + public void wakeup() { + log.info("本地保持唤醒状态"); + Long id = 5L; + mallMemberMapper.selectById(id); + } } diff --git a/src/main/java/cc/mrbird/febs/mall/service/IAdminGroupService.java b/src/main/java/cc/mrbird/febs/mall/service/IAdminGroupService.java new file mode 100644 index 0000000..8c39fed --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/service/IAdminGroupService.java @@ -0,0 +1,7 @@ +package cc.mrbird.febs.mall.service; + +import cc.mrbird.febs.mall.entity.MallGroup; +import com.baomidou.mybatisplus.extension.service.IService; + +public interface IAdminGroupService extends IService<MallGroup> { +} diff --git a/src/main/java/cc/mrbird/febs/mall/service/IAdminMallTeamLeaderService.java b/src/main/java/cc/mrbird/febs/mall/service/IAdminMallTeamLeaderService.java new file mode 100644 index 0000000..b4ac3bf --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/service/IAdminMallTeamLeaderService.java @@ -0,0 +1,23 @@ +package cc.mrbird.febs.mall.service; + +import cc.mrbird.febs.common.entity.FebsResponse; +import cc.mrbird.febs.common.entity.QueryRequest; +import cc.mrbird.febs.mall.dto.AdminLeaderUpdateDto; +import cc.mrbird.febs.mall.entity.MallTeamLeader; +import cc.mrbird.febs.mall.vo.AdminMallTeamLeaderVo; +import cc.mrbird.febs.mall.vo.AdminSelectListLeaderVo; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +public interface IAdminMallTeamLeaderService extends IService<MallTeamLeader> { + + IPage<AdminMallTeamLeaderVo> getLeaderListInPage(MallTeamLeader mallTeamLeader, QueryRequest request); + + AdminMallTeamLeaderVo getMallTeamLederInfoById(long id); + + FebsResponse leaderUpdate(AdminLeaderUpdateDto adminLeaderUpdateDto); + + List<AdminSelectListLeaderVo> selectList(MallTeamLeader mallTeamLeader); +} diff --git a/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java b/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java index ed7ff02..fd5b87a 100644 --- a/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java +++ b/src/main/java/cc/mrbird/febs/mall/service/IApiMallMemberService.java @@ -11,6 +11,7 @@ import cc.mrbird.febs.mall.vo.ShopListVo; import com.baomidou.mybatisplus.extension.service.IService; +import java.io.IOException; import java.math.BigDecimal; import java.util.List; @@ -64,4 +65,10 @@ CashOutSettingVo cashOutSetting(); List<ShopListVo> findShopListVo(ShopListDto shopListDto); + + FebsResponse xcxLogin(ApiXcxLoginDto apiXcxLoginDto) throws IOException; + + FebsResponse xcxSaveInfo(ApiXcxSaveInfoDto apiXcxSaveInfoDto); + + FebsResponse xcxPhoneLogin(ApiXcxPhoneLoginDto apiXcxPhoneLoginDto); } diff --git a/src/main/java/cc/mrbird/febs/mall/service/IApiMallTeamLeaderService.java b/src/main/java/cc/mrbird/febs/mall/service/IApiMallTeamLeaderService.java new file mode 100644 index 0000000..4718121 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/service/IApiMallTeamLeaderService.java @@ -0,0 +1,27 @@ +package cc.mrbird.febs.mall.service; + +import cc.mrbird.febs.common.entity.FebsResponse; +import cc.mrbird.febs.mall.dto.*; +import cc.mrbird.febs.mall.entity.MallTeamLeader; +import cc.mrbird.febs.mall.vo.ApiLeaderListVo; +import cc.mrbird.febs.mall.vo.OrderListVo; +import com.baomidou.mybatisplus.extension.service.IService; + +import java.util.List; + +public interface IApiMallTeamLeaderService extends IService<MallTeamLeader> { + + FebsResponse applyLeader(ApiApplayLeaderDto apiApplayLeaderDto); + + List<ApiLeaderListVo> findLeaderListInPage(ApiLeaderListDto apiLeaderListDto); + + FebsResponse leaderState(); + + FebsResponse getApiLeaderInfoVoById(Long id); + + List<OrderListVo> findLeaderOrderListInPage(ApiLeaderOrderListDto apiLeaderOrderListDto); + + FebsResponse leaderOrderConfirm(ApiLeaderOrderConfirmDto apiLeaderOrderConfirmDto); + + FebsResponse leaderTitle(ApiLeaderTitleDto apiLeaderTitleDto); +} diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminGroupServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminGroupServiceImpl.java new file mode 100644 index 0000000..328401d --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminGroupServiceImpl.java @@ -0,0 +1,17 @@ +package cc.mrbird.febs.mall.service.impl; + +import cc.mrbird.febs.mall.entity.MallGroup; +import cc.mrbird.febs.mall.mapper.MallGroupMapper; +import cc.mrbird.febs.mall.service.IAdminGroupService; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Slf4j +@Service +@RequiredArgsConstructor +@Transactional +public class AdminGroupServiceImpl extends ServiceImpl<MallGroupMapper, MallGroup> implements IAdminGroupService { +} diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java index 203a7bd..4cd454e 100644 --- a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java +++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallOrderService.java @@ -83,6 +83,10 @@ if(2 != status){ return new FebsResponse().fail().message("订单不是待发货状态"); } + Integer deliveryType = mallOrderInfo.getDeliveryType(); + if(2 != deliveryType){ + return new FebsResponse().fail().message("订单的配送方式不是快递"); + } String expressNo = deliverGoodsDto.getExpressNo(); if(StrUtil.isEmpty(expressNo)){ return new FebsResponse().fail().message("请输入物流单号"); diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallTeamLeaderServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallTeamLeaderServiceImpl.java new file mode 100644 index 0000000..fbc4bed --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/service/impl/AdminMallTeamLeaderServiceImpl.java @@ -0,0 +1,79 @@ +package cc.mrbird.febs.mall.service.impl; + +import cc.mrbird.febs.common.entity.FebsResponse; +import cc.mrbird.febs.common.entity.QueryRequest; +import cc.mrbird.febs.mall.conversion.MallTeamLeaderConversion; +import cc.mrbird.febs.mall.dto.AdminLeaderUpdateDto; +import cc.mrbird.febs.mall.entity.MallGoodsCategory; +import cc.mrbird.febs.mall.entity.MallTeamLeader; +import cc.mrbird.febs.mall.mapper.MallTeamLeaderMapper; +import cc.mrbird.febs.mall.service.IAdminMallTeamLeaderService; +import cc.mrbird.febs.mall.vo.AdminMallActSetVo; +import cc.mrbird.febs.mall.vo.AdminMallTeamLeaderVo; +import cc.mrbird.febs.mall.vo.AdminSelectListLeaderVo; +import cn.hutool.core.collection.CollUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +@Transactional +public class AdminMallTeamLeaderServiceImpl extends ServiceImpl<MallTeamLeaderMapper, MallTeamLeader> implements IAdminMallTeamLeaderService { + @Override + public IPage<AdminMallTeamLeaderVo> getLeaderListInPage(MallTeamLeader mallTeamLeader, QueryRequest request) { + Page<AdminMallTeamLeaderVo> page = new Page<>(request.getPageNum(), request.getPageSize()); + IPage<AdminMallTeamLeaderVo> adminMallActSetVos = this.baseMapper.selectLeaderListInPage(page, mallTeamLeader); + return adminMallActSetVos; + } + + @Override + public AdminMallTeamLeaderVo getMallTeamLederInfoById(long id) { + MallTeamLeader mallTeamLeader = this.baseMapper.selectById(id); + AdminMallTeamLeaderVo adminMallTeamLeaderVo = MallTeamLeaderConversion.INSTANCE.entityToVo(mallTeamLeader); + return adminMallTeamLeaderVo; + } + + @Override + public FebsResponse leaderUpdate(AdminLeaderUpdateDto adminLeaderUpdateDto) { + Long id = adminLeaderUpdateDto.getId(); + MallTeamLeader mallTeamLeader = this.baseMapper.selectById(id); + Integer state = mallTeamLeader.getState(); + if(MallTeamLeader.STATE_ING != state){ + return new FebsResponse().fail().message("只有【待审核】状态才能提交!"); + } + int isOk = adminLeaderUpdateDto.getIsOk(); + if(MallTeamLeader.STATE_YES == isOk){ + mallTeamLeader.setState(MallTeamLeader.STATE_YES); + this.baseMapper.updateById(mallTeamLeader); + } + if(MallTeamLeader.STATE_NO == isOk){ + mallTeamLeader.setState(MallTeamLeader.STATE_NO); + this.baseMapper.updateById(mallTeamLeader); + } + return new FebsResponse().success().message("审核成功"); + } + + @Override + public List<AdminSelectListLeaderVo> selectList(MallTeamLeader mallTeamLeader) { + List<AdminSelectListLeaderVo> list = new ArrayList<>(); + List<MallTeamLeader> mallTeamLeaders = this.baseMapper.getMallTeamLeaderList(); + if(CollUtil.isNotEmpty(mallTeamLeaders)){ + for(MallTeamLeader teamLeader : mallTeamLeaders){ + AdminSelectListLeaderVo adminSelectListLeaderVo = new AdminSelectListLeaderVo(); + adminSelectListLeaderVo.setUniqueCode(teamLeader.getUniqueCode()); + adminSelectListLeaderVo.setName(teamLeader.getName()); + list.add(adminSelectListLeaderVo); + } + } + return list; + } +} diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java index ee17af4..d649eb4 100644 --- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java +++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java @@ -6,6 +6,7 @@ import cc.mrbird.febs.common.enumerates.FlowTypeEnum; import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum; import cc.mrbird.febs.common.exception.FebsException; +import cc.mrbird.febs.common.properties.XcxProperties; import cc.mrbird.febs.common.utils.*; import cc.mrbird.febs.mall.conversion.MallMemberConversion; import cc.mrbird.febs.mall.conversion.MallShopApplyConversion; @@ -31,10 +32,12 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import java.io.IOException; import java.math.BigDecimal; import java.util.*; @@ -58,6 +61,7 @@ private final DataDictionaryCustomMapper dataDictionaryCustomMapper; private final MallShopApplyMapper mallShopApplyMapper; private final MallRegisterAppealMapper mallRegisterAppealMapper; + private final MallTeamLeaderMapper mallTeamLeaderMapper; @Value("${spring.profiles.active}") @@ -213,7 +217,8 @@ @Override public FebsResponse logout() { Long id = LoginUserUtil.getLoginUser().getId(); - redisUtils.del(AppContants.APP_LOGIN_PREFIX + id); + redisUtils.del(AppContants.XCX_LOGIN_PREFIX + id); + redisUtils.del(AppContants.XCX_LOGIN_PHONE_PREFIX + id); return new FebsResponse().success().message("退出登录"); } @@ -238,15 +243,23 @@ mallMemberVo.setHasPayment(1); } - DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.AGENT_LEVEL, mallMember.getLevel()); - if (dic != null) { - mallMemberVo.setLevelName(dic.getDescription()); - } +// DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.AGENT_LEVEL, mallMember.getLevel()); +// if (dic != null) { +// mallMemberVo.setLevelName(dic.getDescription()); +// } MallMemberWallet wallet = mallMemberWalletMapper.selectWalletByMemberId(mallMemberVo.getId()); mallMemberVo.setBalance(wallet.getBalance()); mallMemberVo.setScore(wallet.getScore()); mallMemberVo.setPrizeScore(wallet.getPrizeScore()); mallMemberVo.setTotalCost(mallOrderInfoMapper.selectTotalAmount(id)); + + //用户是否是团长 + List<MallTeamLeader> mallTeamLeaders = mallTeamLeaderMapper.selectListByMemberIdAndState(mallMember.getId(), MallTeamLeader.STATE_YES); + if(CollUtil.isNotEmpty(mallTeamLeaders)){ + mallMemberVo.setIsTeamLeader(1); + }else{ + mallMemberVo.setIsTeamLeader(2); + } return new FebsResponse().success().data(mallMemberVo); } @@ -542,4 +555,153 @@ } return MallShopApplyConversion.INSTANCE.entitiesToVOs(list); } + + + private final XcxProperties xcxProperties = SpringContextHolder.getBean(XcxProperties.class); + + @Override + public FebsResponse xcxLogin(ApiXcxLoginDto apiXcxLoginDto) throws IOException { + FebsResponse febsResponse = new FebsResponse(); + String code = apiXcxLoginDto.getCode(); + log.info("code:" + code); + if (StrUtil.isNotBlank(code)) { + String requrl = getXcxLoginUrl(code); + String reslutData = HttpCurlUtil.sendGetHttp(requrl, null); + net.sf.json.JSONObject json = net.sf.json.JSONObject.fromObject(reslutData); + log.info("微信登录获取到登录信息={}", json); + + if (json.containsKey("errcode")) { + log.info("微信登录获取到异常信息errcode"); + return febsResponse.fail().message("自动登录失败"); + } + + String openId = json.getString("openid"); + String sessionKey = json.getString("session_key"); + log.info("openId={},sessionKey={}", openId, sessionKey); + // 查询用户是否存在 + MallMember mallMember = null; + synchronized (this) { + mallMember = this.baseMapper.selectMemberByOpenId(openId); + if (ObjectUtil.isEmpty(mallMember)) { + // 新增用户 + mallMember = new MallMember(); + mallMember.setAccountStatus(MallMember.ACCOUNT_STATUS_ENABLE); + mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL); + mallMember.setLevel(AgentLevelEnum.ZERO_LEVEL.name()); + mallMember.setOpenId(openId); + mallMember.setSessionKey(sessionKey); + this.baseMapper.insert(mallMember); + + mallMember = this.baseMapper.selectMemberByOpenId(openId); + String inviteId = ShareCodeUtil.toSerialCode(mallMember.getId()); + mallMember.setInviteId(inviteId); + this.baseMapper.updateById(mallMember); + MallMemberWallet wallet = new MallMemberWallet(); + wallet.setBalance(BigDecimal.ZERO); + wallet.setMemberId(mallMember.getId()); + mallMemberWalletMapper.insert(wallet); + } else { + mallMember.setSessionKey(sessionKey); + this.baseMapper.updateById(mallMember); + } + } + // 存放redis + String redisKey = AppContants.XCX_LOGIN_PREFIX + mallMember.getId(); + String existToken = redisUtils.getString(redisKey); + if (StrUtil.isNotBlank(existToken)) { + Object o = redisUtils.get(existToken); + if (ObjectUtil.isNotEmpty(o)) { + redisUtils.del(existToken); + } + } + String token = IdUtil.simpleUUID(); + redisUtils.set(token, JSONObject.toJSONString(mallMember), 360000); + redisUtils.set(redisKey, token, 360000); + Map<String, Object> authInfo = new HashMap<>(); + authInfo.put("token", token); + authInfo.put("appid", xcxProperties.getXcxAppid()); + authInfo.put("member", mallMember); + authInfo.put("rasToken", generateAsaToken(token)); + febsResponse.success().data(authInfo); + } else { + return febsResponse.fail().message("自动登录失败"); + } + return febsResponse; + } + + @Override + public FebsResponse xcxSaveInfo(ApiXcxSaveInfoDto apiXcxSaveInfoDto) { + log.info("name={},phone={},avatar={},sex={}", + apiXcxSaveInfoDto.getNickName(),apiXcxSaveInfoDto.getPhone(),apiXcxSaveInfoDto.getAvatarUrl(),apiXcxSaveInfoDto.getGender()); + Long memberId = LoginUserUtil.getLoginUser().getId(); + MallMember mallMember = this.baseMapper.selectById(memberId); + String nickName = apiXcxSaveInfoDto.getNickName(); + if(StrUtil.isNotEmpty(nickName)){ + mallMember.setName(nickName); + } + String phone = apiXcxSaveInfoDto.getPhone(); + if(StrUtil.isNotEmpty(phone)){ + mallMember.setPhone(phone); + } + String avatarUrl = apiXcxSaveInfoDto.getAvatarUrl(); + if(StrUtil.isNotEmpty(avatarUrl)){ + mallMember.setAvatar(avatarUrl); + } + mallMember.setSex(apiXcxSaveInfoDto.getGender() == 1 ? "女" : "男"); + this.baseMapper.updateById(mallMember); + return new FebsResponse().success(); + } + + @Override + public FebsResponse xcxPhoneLogin(ApiXcxPhoneLoginDto apiXcxPhoneLoginDto) { + String phone = apiXcxPhoneLoginDto.getPhone(); + boolean flag = commonService.verifyCode(phone, apiXcxPhoneLoginDto.getCode()); + if (flag) { + // 查询用户是否存在 + MallMember mallMember = null; + synchronized (this) { + mallMember = this.baseMapper.selectInfoByAccount(apiXcxPhoneLoginDto.getPhone()); + if (ObjectUtil.isEmpty(mallMember)) { + // 新增用户 + mallMember = new MallMember(); + mallMember.setPhone(phone); + mallMember.setAccountStatus(MallMember.ACCOUNT_STATUS_ENABLE); + mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL); + mallMember.setLevel(AgentLevelEnum.ZERO_LEVEL.name()); + this.baseMapper.insert(mallMember); + + String inviteId = ShareCodeUtil.toSerialCode(mallMember.getId()); + mallMember.setInviteId(inviteId); + this.baseMapper.updateById(mallMember); + MallMemberWallet wallet = new MallMemberWallet(); + wallet.setBalance(BigDecimal.ZERO); + wallet.setMemberId(mallMember.getId()); + mallMemberWalletMapper.insert(wallet); + } + } + // 存放redis + String redisKey = AppContants.XCX_LOGIN_PHONE_PREFIX + mallMember.getId(); + String existToken = redisUtils.getString(redisKey); + if (StrUtil.isNotBlank(existToken)) { + Object o = redisUtils.get(existToken); + if (ObjectUtil.isNotEmpty(o)) { + redisUtils.del(existToken); + } + } + String token = IdUtil.simpleUUID(); + redisUtils.set(token, JSONObject.toJSONString(mallMember), 360000); + redisUtils.set(redisKey, token, 360000); + Map<String, Object> authInfo = new HashMap<>(); + authInfo.put("token", token); + authInfo.put("member", mallMember); + authInfo.put("rasToken", generateAsaToken(token)); + return new FebsResponse().success().message("登陆成功"); + } + return new FebsResponse().fail().message("验证码错误"); + } + + private String getXcxLoginUrl(String code) { + String wechatLoginUrl =xcxProperties.getWecharLoginUrl(); + return String.format(wechatLoginUrl, xcxProperties.getXcxAppid(), xcxProperties.getXcxSecret(), code); + } } diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java index 300a206..62c8152 100644 --- a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java +++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java @@ -2,10 +2,7 @@ import cc.mrbird.febs.common.enumerates.*; import cc.mrbird.febs.common.exception.FebsException; -import cc.mrbird.febs.common.utils.AppContants; -import cc.mrbird.febs.common.utils.LoginUserUtil; -import cc.mrbird.febs.common.utils.MallUtils; -import cc.mrbird.febs.common.utils.RedisUtils; +import cc.mrbird.febs.common.utils.*; import cc.mrbird.febs.mall.conversion.MallGoodsCommentConversion; import cc.mrbird.febs.mall.conversion.MallOrderInfoConversion; import cc.mrbird.febs.mall.conversion.MallOrderRefundConversion; @@ -16,7 +13,9 @@ import cc.mrbird.febs.mall.vo.OrderDetailVo; import cc.mrbird.febs.mall.vo.OrderListVo; import cc.mrbird.febs.mall.vo.OrderRefundVo; +import cc.mrbird.febs.pay.model.BrandWCPayRequestData; import cc.mrbird.febs.pay.service.IPayService; +import cc.mrbird.febs.pay.service.IXcxPayService; import cc.mrbird.febs.rabbit.producter.AgentProducer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateUnit; @@ -60,6 +59,7 @@ private final AgentProducer agentProducer; private final IPayService payService; + private final IXcxPayService iXcxPayService; private final IMallAchieveService mallAchieveService; @Override @@ -85,6 +85,9 @@ orderInfo.setLongitude(address.getLongitude()); orderInfo.setRemark(addOrderDto.getRemark()); orderInfo.setOrderType(addOrderDto.getOrderType()); + + orderInfo.setTakeUniqueCode(addOrderDto.getTakeUniqueCode()); + orderInfo.setDeliveryType(1); if (CollUtil.isEmpty(addOrderDto.getItems())) { throw new FebsException("参数错误"); @@ -216,6 +219,13 @@ case "1": // orderInfo.setPayOrderNo(payOrderDto.getPayOrderNo()); // orderInfo.setPayImage(payOrderDto.getPayImage()); + BrandWCPayRequestData brandWCPayRequestData = null; + try { + brandWCPayRequestData = iXcxPayService.startPayment(orderInfo); + } catch (Exception e) { + throw new FebsException("支付失败"); + } + payResultStr = brandWCPayRequestData.getPrepay_id(); orderInfo.setPayMethod("微信支付"); agentProducer.sendOrderReturn(orderInfo.getId()); break; @@ -294,6 +304,9 @@ default: } + //订单支付成功产生一个提货码 + String takeCode = ShareCodeUtil.toSerialCode(orderInfo.getId()); + orderInfo.setTakeCode(takeCode); this.baseMapper.updateById(orderInfo); Map<String, Object> map = new HashMap<>(); diff --git a/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallTeamLeaderServiceImpl.java b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallTeamLeaderServiceImpl.java new file mode 100644 index 0000000..0b5f278 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallTeamLeaderServiceImpl.java @@ -0,0 +1,165 @@ +package cc.mrbird.febs.mall.service.impl; + +import cc.mrbird.febs.common.entity.FebsResponse; +import cc.mrbird.febs.common.enumerates.OrderStatusEnum; +import cc.mrbird.febs.common.utils.LoginUserUtil; +import cc.mrbird.febs.common.utils.ShareCodeUtil; +import cc.mrbird.febs.mall.conversion.MallOrderInfoConversion; +import cc.mrbird.febs.mall.conversion.MallTeamLeaderConversion; +import cc.mrbird.febs.mall.dto.*; +import cc.mrbird.febs.mall.entity.MallExpressInfo; +import cc.mrbird.febs.mall.entity.MallMember; +import cc.mrbird.febs.mall.entity.MallOrderInfo; +import cc.mrbird.febs.mall.entity.MallTeamLeader; +import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; +import cc.mrbird.febs.mall.mapper.MallTeamLeaderMapper; +import cc.mrbird.febs.mall.service.IApiMallTeamLeaderService; +import cc.mrbird.febs.mall.vo.ApiLeaderInfoVo; +import cc.mrbird.febs.mall.vo.ApiLeaderListVo; +import cc.mrbird.febs.mall.vo.ApiMallleaderStateVo; +import cc.mrbird.febs.mall.vo.OrderListVo; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +@Slf4j +@Service +@RequiredArgsConstructor +public class ApiMallTeamLeaderServiceImpl extends ServiceImpl<MallTeamLeaderMapper, MallTeamLeader> implements IApiMallTeamLeaderService { + + @Override + @Transactional + public FebsResponse applyLeader(ApiApplayLeaderDto apiApplayLeaderDto) { + MallMember member = LoginUserUtil.getLoginUser(); + Long memberId = member.getId(); + List<MallTeamLeader> mallTeamLeaders = this.baseMapper.selectListByMemberIdAndState(memberId, MallTeamLeader.STATE_ING); + if(CollUtil.isNotEmpty(mallTeamLeaders)){ + return new FebsResponse().fail().message("正在申请中"); + } + MallTeamLeader mallTeamLeader = MallTeamLeaderConversion.INSTANCE.dtoToEntity(apiApplayLeaderDto); + mallTeamLeader.setMemberId(memberId); + mallTeamLeader.setState(MallTeamLeader.STATE_ING); + mallTeamLeader.setUniqueCode(member.getInviteId()); + this.baseMapper.insert(mallTeamLeader); + return new FebsResponse().success().message("申请成功"); + } + + @Override + public List<ApiLeaderListVo> findLeaderListInPage(ApiLeaderListDto apiLeaderListDto) { + Page<MallTeamLeader> page = new Page<>(apiLeaderListDto.getPageNum(), apiLeaderListDto.getPageSize()); + IPage<MallTeamLeader> mallTeamLeaderIPage = this.baseMapper.selectApiLeaderListInPage(page, apiLeaderListDto); + return MallTeamLeaderConversion.INSTANCE.entitysToVos(mallTeamLeaderIPage.getRecords()); + } + + @Override + public FebsResponse leaderState() { + MallMember member = LoginUserUtil.getLoginUser(); + Long memberId = member.getId(); + ApiMallleaderStateVo apiMallleaderStateVo = new ApiMallleaderStateVo(); + List<MallTeamLeader> mallTeamLeadersIng = this.baseMapper.selectListByMemberIdAndState(memberId, MallTeamLeader.STATE_ING); + List<MallTeamLeader> mallTeamLeadersNo = this.baseMapper.selectListByMemberIdAndState(memberId, MallTeamLeader.STATE_NO); + List<MallTeamLeader> mallTeamLeadersYes = this.baseMapper.selectListByMemberIdAndState(memberId, MallTeamLeader.STATE_YES); + if(CollUtil.isNotEmpty(mallTeamLeadersIng) ||CollUtil.isNotEmpty(mallTeamLeadersYes)){ + apiMallleaderStateVo.setState(2); + }else if(CollUtil.isNotEmpty(mallTeamLeadersNo)){ + apiMallleaderStateVo.setState(1); + }else{ + apiMallleaderStateVo.setState(1); + } + return new FebsResponse().success().data(apiMallleaderStateVo); + } + + @Override + public FebsResponse getApiLeaderInfoVoById(Long id) { + MallTeamLeader mallTeamLeader = this.baseMapper.selectById(id); + ApiLeaderInfoVo apiLeaderInfoVo = new ApiLeaderInfoVo(); + apiLeaderInfoVo.setName(mallTeamLeader.getName()); + apiLeaderInfoVo.setPhone(mallTeamLeader.getPhone()); + apiLeaderInfoVo.setAddressPic(mallTeamLeader.getAddressPic()); + apiLeaderInfoVo.setUniqueCode(mallTeamLeader.getUniqueCode()); + apiLeaderInfoVo.setProvince(mallTeamLeader.getProvince()); + apiLeaderInfoVo.setCity(mallTeamLeader.getCity()); + apiLeaderInfoVo.setTownship(mallTeamLeader.getTownship()); + apiLeaderInfoVo.setDetailAddress(mallTeamLeader.getDetailAddress()); + apiLeaderInfoVo.setAddressArea(mallTeamLeader.getAddressArea()); + return new FebsResponse().success().data(apiLeaderInfoVo); + } + + @Override + public List<OrderListVo> findLeaderOrderListInPage(ApiLeaderOrderListDto apiLeaderOrderListDto) { + MallMember member = LoginUserUtil.getLoginUser(); + IPage<MallOrderInfo> page = new Page<>(apiLeaderOrderListDto.getPageNum(), apiLeaderOrderListDto.getPageSize()); + apiLeaderOrderListDto.setMemberId(member.getId()); + IPage<MallOrderInfo> mallOrderInfos = this.baseMapper.selectApiLeaderOrderListInPage(page, apiLeaderOrderListDto); + return MallOrderInfoConversion.INSTANCE.entitysToVos(mallOrderInfos.getRecords()); + } + + private final MallOrderInfoMapper mallOrderInfoMapper; + + @Override + @Transactional + public FebsResponse leaderOrderConfirm(ApiLeaderOrderConfirmDto apiLeaderOrderConfirmDto) { + MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectByOrderNo(apiLeaderOrderConfirmDto.getOrderNo()); + if(ObjectUtil.isEmpty(mallOrderInfo)){ + return new FebsResponse().fail().message("订单不存在"); + } + Integer status = mallOrderInfo.getStatus(); + if(OrderStatusEnum.WAIT_SHIPPING.getValue() != status){ + return new FebsResponse().fail().message("订单不是待确认到货状态"); + } + Integer deliveryType = mallOrderInfo.getDeliveryType(); + if(1 != deliveryType){ + return new FebsResponse().fail().message("订单的配送方式不是自提"); + } + mallOrderInfo.setStatus(OrderStatusEnum.WAIT_FINISH.getValue()); + mallOrderInfoMapper.updateById(mallOrderInfo); + return new FebsResponse().success().message("确认成功"); + } + + @Override + public FebsResponse leaderTitle(ApiLeaderTitleDto apiLeaderTitleDto) { + String uniqueCode = apiLeaderTitleDto.getUniqueCode(); + Double longitude = apiLeaderTitleDto.getLongitude() == null ? 0 : apiLeaderTitleDto.getLongitude(); + Double latitude = apiLeaderTitleDto.getLatitude() == null ? 0 : apiLeaderTitleDto.getLatitude(); + ApiLeaderInfoVo apiLeaderInfoVo = new ApiLeaderInfoVo(); + MallTeamLeader mallTeamLeader = new MallTeamLeader(); + //特征码扫码 + if(StrUtil.isNotEmpty(uniqueCode)){ + mallTeamLeader = this.baseMapper.selectLeaderByUniqueCode(uniqueCode); + + //经纬度定位 + }else if(longitude != 0 && latitude != 0){ + mallTeamLeader = this.baseMapper.selectLeaderByLonAndLat(longitude,latitude); + + //直接进入,默认选择列表第一个 + }else{ + List<MallTeamLeader> mallTeamLeaderList = this.baseMapper.getMallTeamLeaderList(); + if(CollUtil.isNotEmpty(mallTeamLeaderList)){ + mallTeamLeader = mallTeamLeaderList.get(0); + } + } + if(ObjectUtil.isNotEmpty(mallTeamLeader)){ + apiLeaderInfoVo.setId(mallTeamLeader.getId()); + apiLeaderInfoVo.setName(mallTeamLeader.getName()); + apiLeaderInfoVo.setPhone(mallTeamLeader.getPhone()); + apiLeaderInfoVo.setAddressPic(mallTeamLeader.getAddressPic()); + apiLeaderInfoVo.setUniqueCode(mallTeamLeader.getUniqueCode()); + apiLeaderInfoVo.setProvince(mallTeamLeader.getProvince()); + apiLeaderInfoVo.setCity(mallTeamLeader.getCity()); + apiLeaderInfoVo.setTownship(mallTeamLeader.getTownship()); + apiLeaderInfoVo.setDetailAddress(mallTeamLeader.getDetailAddress()); + apiLeaderInfoVo.setAddressArea(mallTeamLeader.getAddressArea()); + } + return new FebsResponse().success().data(apiLeaderInfoVo); + } + +} diff --git a/src/main/java/cc/mrbird/febs/mall/vo/AdminMallOrderInfoVo.java b/src/main/java/cc/mrbird/febs/mall/vo/AdminMallOrderInfoVo.java index a0e3f12..f5caa96 100644 --- a/src/main/java/cc/mrbird/febs/mall/vo/AdminMallOrderInfoVo.java +++ b/src/main/java/cc/mrbird/febs/mall/vo/AdminMallOrderInfoVo.java @@ -71,4 +71,6 @@ private String memberEmail; private Integer carriage; + //配送方式 1:自提 2:快递 + private Integer deliveryType; } diff --git a/src/main/java/cc/mrbird/febs/mall/vo/AdminMallTeamLeaderVo.java b/src/main/java/cc/mrbird/febs/mall/vo/AdminMallTeamLeaderVo.java new file mode 100644 index 0000000..6c37995 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/vo/AdminMallTeamLeaderVo.java @@ -0,0 +1,40 @@ +package cc.mrbird.febs.mall.vo; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +import java.util.Date; + +@Data +@ApiModel(value = "AdminMallTeamLeaderVo", description = "信息返回类") +public class AdminMallTeamLeaderVo { + + //ID + private Long id; + //用户ID + private Long memberId; + //申请状态 1:审核通过 2:审核不通过 3:申请中 + private Integer state; + //团长姓名 + private String name; + //手机号码 + private String phone; + //自提点照片 + private String addressPic; + //省 + private String province; + //市 + private String city; + //区 + private String township; + //小区名称(自提点名称) + private String addressArea; + //详细地址 + private String detailAddress; + //经度 + private Double longitude; + //纬度 + private Double latitude; + + private Date createdTime; +} diff --git a/src/main/java/cc/mrbird/febs/mall/vo/AdminSelectListLeaderVo.java b/src/main/java/cc/mrbird/febs/mall/vo/AdminSelectListLeaderVo.java new file mode 100644 index 0000000..d931ebc --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/vo/AdminSelectListLeaderVo.java @@ -0,0 +1,14 @@ +package cc.mrbird.febs.mall.vo; + +import io.swagger.annotations.ApiModel; +import lombok.Data; + +@Data +@ApiModel(value = "AdminSelectListLeaderVo", description = "信息返回类") +public class AdminSelectListLeaderVo { + + private String uniqueCode; + + private String name; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderInfoVo.java b/src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderInfoVo.java new file mode 100644 index 0000000..7ceb31d --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderInfoVo.java @@ -0,0 +1,39 @@ +package cc.mrbird.febs.mall.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(value = "ApiLeaderInfoVo", description = "信息返回类") +public class ApiLeaderInfoVo { + + private Long id; + //团长姓名 + @ApiModelProperty(value = "团长姓名") + private String name; + //手机号码 + @ApiModelProperty(value = "手机号码") + private String phone; + //团长特征码 + @ApiModelProperty(value = "团长特征码") + private String uniqueCode; + //自提点照片 + @ApiModelProperty(value = "自提点照片") + private String addressPic; + //省 + @ApiModelProperty(value = "省") + private String province; + //市 + @ApiModelProperty(value = "市") + private String city; + //区 + @ApiModelProperty(value = "区") + private String township; + //小区名称 + @ApiModelProperty(value = "小区名称(自提点名称)") + private String addressArea; + //详细地址 + @ApiModelProperty(value = "详细地址") + private String detailAddress; +} diff --git a/src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderListVo.java b/src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderListVo.java new file mode 100644 index 0000000..abf9e85 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/vo/ApiLeaderListVo.java @@ -0,0 +1,50 @@ +package cc.mrbird.febs.mall.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(value = "AdminMallTeamLeaderVo", description = "信息返回类") +public class ApiLeaderListVo { + + private Long id; + //团长姓名 + @ApiModelProperty(value = "团长姓名") + private String name; + //手机号码 + @ApiModelProperty(value = "手机号码") + private String phone; + //团长特征码 + @ApiModelProperty(value = "团长特征码") + private String uniqueCode; + //自提点照片 + @ApiModelProperty(value = "自提点照片") + private String addressPic; + //省 + @ApiModelProperty(value = "省") + private String province; + //市 + @ApiModelProperty(value = "市") + private String city; + //区 + @ApiModelProperty(value = "区") + private String township; + //小区名称 + @ApiModelProperty(value = "小区名称(自提点名称)") + private String addressArea; + //详细地址 + @ApiModelProperty(value = "详细地址") + private String detailAddress; + + @ApiModelProperty(value = "距离") + private Double distance; + //经度 + + @ApiModelProperty(value = "经度") + private Double longitude; + //纬度 + + @ApiModelProperty(value = "纬度") + private Double latitude; +} diff --git a/src/main/java/cc/mrbird/febs/mall/vo/ApiMallleaderStateVo.java b/src/main/java/cc/mrbird/febs/mall/vo/ApiMallleaderStateVo.java new file mode 100644 index 0000000..9e634f3 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/mall/vo/ApiMallleaderStateVo.java @@ -0,0 +1,14 @@ +package cc.mrbird.febs.mall.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +@Data +@ApiModel(value = "ApiMallTeamLeaderVo", description = "信息返回类") +public class ApiMallleaderStateVo { + + @ApiModelProperty(value = "1:可申请 2:不可申请") + private Integer state; + +} diff --git a/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java b/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java index b78cb76..caa6004 100644 --- a/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java +++ b/src/main/java/cc/mrbird/febs/mall/vo/MallMemberVo.java @@ -27,7 +27,7 @@ @ApiModelProperty(value = "性别") private String sex; - @ApiModelProperty(value = "邀请码") + @ApiModelProperty(value = "邀请码(如果是团长,邀请码就是团长特征码)") private String inviteId; @ApiModelProperty(value = "头像") @@ -72,4 +72,7 @@ @ApiModelProperty(value = "抽奖积分") private BigDecimal prizeScore; + @ApiModelProperty(value = "是否是团长 1: 是 2:否") + private Integer isTeamLeader; + } diff --git a/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java b/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java index 78242f6..2ce0603 100644 --- a/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java +++ b/src/main/java/cc/mrbird/febs/mall/vo/OrderDetailVo.java @@ -1,5 +1,6 @@ package cc.mrbird.febs.mall.vo; +import com.baomidou.mybatisplus.annotation.TableField; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; @@ -84,5 +85,27 @@ @ApiModelProperty(value = "评价状态 1:待评价 2:已评价") private Integer commentState; + //提货码 + @ApiModelProperty(value = "提货码") + private String takeCode; + /** + * 自提点信息 + */ + @ApiModelProperty(value = "团长姓名") + private String leaderName; + @ApiModelProperty(value = "团长电话") + private String leaderPhone; + @ApiModelProperty(value = "自提点图片") + private String addressPic; + @ApiModelProperty(value = "自提点省") + private String province; + @ApiModelProperty(value = "自提点市") + private String city; + @ApiModelProperty(value = "自提点区") + private String township; + @ApiModelProperty(value = "自提点名称") + private String addressArea; + @ApiModelProperty(value = "自提点详细地址") + private String detailAddress; } diff --git a/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java b/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java index 21266e9..436fe31 100644 --- a/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java +++ b/src/main/java/cc/mrbird/febs/mall/vo/OrderListVo.java @@ -42,4 +42,7 @@ @ApiModelProperty(value = "评价状态 1:待评价 2:已评价") private Integer commentState; + + @ApiModelProperty(value = "提货码") + private String takeCode; } diff --git a/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java new file mode 100644 index 0000000..4175218 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/controller/XcxPayController.java @@ -0,0 +1,131 @@ +package cc.mrbird.febs.pay.controller; + +import cc.mrbird.febs.common.entity.FebsResponse; +import cc.mrbird.febs.common.enumerates.OrderStatusEnum; +import cc.mrbird.febs.mall.entity.MallOrderInfo; +import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; +import cc.mrbird.febs.pay.model.NotifyData; +import cc.mrbird.febs.pay.util.PayThreadPool; +import cc.mrbird.febs.pay.util.Signature; +import cc.mrbird.febs.pay.util.Util; +import cc.mrbird.febs.pay.util.WechatConfigure; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.math.BigDecimal; +import java.math.RoundingMode; + +@Slf4j +@RestController +@RequestMapping(value = "/api/xcxPay") +public class XcxPayController { + + @Autowired + MallOrderInfoMapper mallOrderInfoMapper; + /** + * 微信支付回调接口 + */ + @Transactional(rollbackFor = Exception.class) + @RequestMapping(value = "/wxpayCallback") + public void payCallBack(HttpServletResponse response, HttpServletRequest request) throws IOException { + log.info("微信支付回调start...."); + + // 获取输入参数 + String inputLine; + StringBuffer notityXml = new StringBuffer(); + String resXml = ""; + String orderId = ""; + + FebsResponse threadResult = new FebsResponse(); + try { + while ((inputLine = request.getReader().readLine()) != null) { + notityXml.append(inputLine); + } + request.getReader().close(); + log.info("notityXml ---- :{} ", notityXml); + + + // XMl转对象 + Object bb = Util.getObjectFromXML(notityXml.toString(), NotifyData.class); + NotifyData data = new NotifyData(); + BeanUtils.copyProperties(bb,data); + log.info("----return_code = {}", data.getReturn_code()); + + + // 返回状态码 SUCCESS/FAIL + if (WechatConfigure.CODE_SUCCESS.equals(data.getReturn_code())) { + + orderId = data.getAttach(); + // 检验订单状态 + MallOrderInfo order = mallOrderInfoMapper.selectById(Long.valueOf(orderId)); + + // 校验签名 + String paySecret = WechatConfigure.WECHARPAY_SECRET; + if (Signature.checkIsSignValidFromResponseString(notityXml.toString(),paySecret)) { + // 校验业务结果 + if (WechatConfigure.CODE_SUCCESS.equals(data.getResult_code())) { + // 返回SUCCESS报文 + resXml = WechatConfigure.RESULT_XML_SUCCESS; + // 支付费用 + Double total_fee = Double.parseDouble(data.getTotal_fee()); + // 商户订单号 + String payNum = data.getOut_trade_no(); + + log.info("支付回调关键信息---total_fee:{},payNum:{},orderId:{}", total_fee, payNum, orderId); + // 订单ID + BigDecimal payMoney = new BigDecimal(total_fee).divide(new BigDecimal(100), 2, + RoundingMode.HALF_UP); + + + if (order != null && OrderStatusEnum.WAIT_PAY.getValue() == order.getStatus()) { + log.debug("检查支付金额payMoney={},order.getPayMoney()={}", payMoney, order.getAmount()); + order.setStatus(OrderStatusEnum.WAIT_SHIPPING.getValue()); + mallOrderInfoMapper.updateById(order); + threadResult.success().message("支付成功"); + } else { + log.info("订单状态不为待付款,order status=", order.getStatus()); + } + } else { + log.info("微信标识业务是失败"); + threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:001)"); +// resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败"); + } + } else { + log.info("无效签名"); + threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:002)"); +// resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "微信标识业务是失败"); + } + } else { + log.info("通信标识失败"); + threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:003)"); +// resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "通信标识失败"); + } + } catch (Exception e) { + log.error("支付回调签名错误", e); + threadResult.fail().message("查询支付信息失败,请联系客服或者刷新支付信息(错误码:004)"); +// resXml = AppConstance.RESULT_XML_FAIL.replace(ERRORMSG, "支付回调签名错误"); + } finally { + // 通知线程消息 + PayThreadPool.notifyThread(Integer.valueOf(orderId), threadResult); + sendResultBack(response, resXml); + } + return; + + } + + private void sendResultBack(HttpServletResponse response, String resXml) throws IOException { + log.info("返回微信数据={}", resXml); + ServletOutputStream out = response.getOutputStream(); + out.write(resXml.getBytes()); + out.flush(); + out.close(); + } +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/BrandWCPayRequestData.java b/src/main/java/cc/mrbird/febs/pay/model/BrandWCPayRequestData.java new file mode 100644 index 0000000..a605255 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/BrandWCPayRequestData.java @@ -0,0 +1,117 @@ +package cc.mrbird.febs.pay.model; + +import cc.mrbird.febs.common.utils.AppContants; +import cc.mrbird.febs.pay.util.RandomStringGenerator; +import cc.mrbird.febs.pay.util.Signature; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +public class BrandWCPayRequestData { + + //每个字段具体的意思请查看API文档 + private String appId = ""; + private String timeStamp = ""; + private String nonceStr = ""; + private String prepay_id = ""; + private String signType = ""; + private String paySign = ""; + + public BrandWCPayRequestData(String prepay_id, String appID, String paySecret){ + //默认必须设置 + setAppId(appID); + //随机字符串,不长于32 位 + setNonceStr(RandomStringGenerator.getRandomStringByLength(32)); + setTimeStamp(Long.toString(System.currentTimeMillis() / 1000L)); + setPrepay_id("prepay_id="+prepay_id); + //根据API给的签名规则进行签名 【 必须要放在本方法的最后】 + setSignType(AppContants.SIGN_MD5); + String sign = Signature.getSign(toMap(),paySecret); + setPaySign(sign);//把签名数据设置到Sign这个属性中 + } + + public String getAppId() { + return appId; + } + + + public void setAppId(String appId) { + this.appId = appId; + } + + + public String getTimeStamp() { + return timeStamp; + } + + + public void setTimeStamp(String timeStamp) { + this.timeStamp = timeStamp; + } + + + public String getNonceStr() { + return nonceStr; + } + + + public void setNonceStr(String nonceStr) { + this.nonceStr = nonceStr; + } + + + public String getPrepay_id() { + return prepay_id; + } + + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + + public String getSignType() { + return signType; + } + + + public void setSignType(String signType) { + this.signType = signType; + } + + + public String getPaySign() { + return paySign; + } + + + public void setPaySign(String paySign) { + this.paySign = paySign; + } + + + public Map<String,Object> toMap(){ + Map<String,Object> map = new HashMap<String, Object>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + Object obj; + try { + obj = field.get(this); + if(obj!=null){ + if(field.getName().equals("prepay_id")){ + map.put("package", obj); + }else{ + map.put(field.getName(), obj); + } + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return map; + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/JsApiPayBusiness.java b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayBusiness.java new file mode 100644 index 0000000..d6a1c2b --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayBusiness.java @@ -0,0 +1,141 @@ +package cc.mrbird.febs.pay.model; + +import cc.mrbird.febs.pay.service.impl.JsApiPayComService; +import cc.mrbird.febs.pay.service.impl.JsApiPayService; +import cc.mrbird.febs.pay.service.impl.RefundService; +import cc.mrbird.febs.pay.service.impl.ScanPayQueryService; +import cc.mrbird.febs.pay.util.Util; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.BeanUtils; + +@Slf4j +public class JsApiPayBusiness { + + private JsApiPayService jsApiPayService; + + public JsApiPayBusiness() throws Exception { + jsApiPayService = new JsApiPayService(); + } + + + + /** + * + * 生成预付订单 + * @author:姜友瑶 + * 返回类型 void + * @throws Exception + * @date 2016年10月13日 + */ + public JsApiPayResData createPrapareOrder(JsApiPayReqData jsApiPayReqData) throws Exception { + // 接受API返回 + String payServiceResponseString; + + long costTimeStart = System.currentTimeMillis(); + + payServiceResponseString = jsApiPayService.request(jsApiPayReqData); + + long costTimeEnd = System.currentTimeMillis(); + long totalTimeCost = costTimeEnd - costTimeStart; + + log.info("------------------request createPrapareOrder taking :" + totalTimeCost + "ms"+"--response="+payServiceResponseString); + + // 将从API返回的XML数据映射到Java对象 + Object data = Util.getObjectFromXML(payServiceResponseString, + JsApiPayResData.class); + JsApiPayResData jsApiPayResData=new JsApiPayResData(); + BeanUtils.copyProperties(data,jsApiPayResData); + return jsApiPayResData; + } + + /** + * + * 支付成功后查询微信订单 + * @author:jiangyouyao + * 返回类型 void + * @throws Exception + * @date 2016年10月13日 + */ + public ScanPayQueryResData queryPrapareOrder(ScanPayQueryService scanPayQueryService , ScanPayQueryReqData scanPayQueryReqData) throws Exception { + // 接受API返回 + String payServiceResponseString; + + long costTimeStart = System.currentTimeMillis(); + + payServiceResponseString = scanPayQueryService.request(scanPayQueryReqData); + + long costTimeEnd = System.currentTimeMillis(); + long totalTimeCost = costTimeEnd - costTimeStart; + + log.info("------------------request createPrapareOrder taking :" + totalTimeCost + "ms"+"--response="+payServiceResponseString); + + // 将从API返回的XML数据映射到Java对象 + ScanPayQueryResData scanPayQueryResData = (ScanPayQueryResData) Util.getObjectFromXML(payServiceResponseString, + ScanPayQueryResData.class); + + return scanPayQueryResData; + } + + + /** + * + * 专家提现,商家向用户(该系统中的专家)支付 + * @author:jiangyouyao + * 返回类型 void + * @throws Exception + * @date 2017年5月25日 + */ + public JsApiPayComResData payComOrder(JsApiPayComService jsApiPayComService , JsApiPayComReqData jsApiPayComReqData) throws Exception { + // 接受API返回 + String payServiceResponseString; + + long costTimeStart = System.currentTimeMillis(); + + payServiceResponseString = jsApiPayComService.request(jsApiPayComReqData); + + long costTimeEnd = System.currentTimeMillis(); + + long totalTimeCost = costTimeEnd - costTimeStart; + + log.info("------------------request createPrapareOrder taking :" + totalTimeCost + "ms"+"--response="+payServiceResponseString); + + // 将从API返回的XML数据映射到Java对象 + JsApiPayComResData jsApiPayComResData = (JsApiPayComResData) Util.getObjectFromXML(payServiceResponseString, + JsApiPayComResData.class); + + return jsApiPayComResData; + } + + + /** + * + * 退款,商家向用户(该系统中的专家)支付 + * @author:jiangyouyao + * @param scanPayReqData + * 返回类型 void + * @throws Exception + * @date 2017年5月25日 + */ + public RefundResData refundComOrder(RefundService refundService , RefundReqData refundReqData) throws Exception { + // 接受API返回 + String payServiceResponseString; + + long costTimeStart = System.currentTimeMillis(); + + payServiceResponseString = refundService.request(refundReqData); + + long costTimeEnd = System.currentTimeMillis(); + + long totalTimeCost = costTimeEnd - costTimeStart; + + log.info("------------------request createPrapareOrder taking :" + totalTimeCost + "ms"+"--response="+payServiceResponseString); + + // 将从API返回的XML数据映射到Java对象 + RefundResData RefundResData = (RefundResData) Util.getObjectFromXML(payServiceResponseString, + RefundResData.class); + + return RefundResData; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/JsApiPayComReqData.java b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayComReqData.java new file mode 100644 index 0000000..8e16c77 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayComReqData.java @@ -0,0 +1,179 @@ +package cc.mrbird.febs.pay.model; + + +import cc.mrbird.febs.pay.util.RandomStringGenerator; +import cc.mrbird.febs.pay.util.Signature; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * 企业支付请求参数 + * + * @author:jiangyouyao + * @date 2017年5月25日 + */ +public class JsApiPayComReqData { + + //每个字段具体的意思请查看API文档 + /** + * 商户号 + */ + private String mchid = ""; + + private String mch_appid = ""; + + /** + * 商户企业付款单号 + */ + private String partner_trade_no = ""; + + /** + * 随机字符串 + */ + private String nonce_str = ""; + + + private String check_name = ""; + + + /** + * 签名 + */ + private String sign = ""; + + /** + * 付款金额 RMB(分) + */ + private int amount = 0; + /** + * 备注 + */ + private String desc = ""; + + private String openid = ""; + + + public JsApiPayComReqData() { + } + + + /** + * + * @author wzy + * @param desc 描述 + * @param outTradeNo 商户企业付款单号 + * @param totalFee 付款金额 + * @param bankCode 收款号开户行 + */ + public JsApiPayComReqData(String mchID,String mch_appid,String paySecret ,String desc, String outTradeNo, int totalFee, + String openid, String check_name, String bankCode) { + setMch_appid(mch_appid); + //默认必须设置 + setMchid(mchID); + setDesc(desc); + setPartner_trade_no(outTradeNo); + setAmount(totalFee); + setOpenid(openid); + setCheck_name(check_name); + //随机字符串,不长于32 位 + setNonce_str(RandomStringGenerator.getRandomStringByLength(32)); + //根据API给的签名规则进行签名 【 必须要放在本方法的最后】 + String sign = Signature.getSign(toMap(),paySecret); + setSign(sign);//把签名数据设置到Sign这个属性中 + + + } + + public String getMch_appid() { + return mch_appid; + } + + public void setMch_appid(String mch_appid) { + this.mch_appid = mch_appid; + } + + public String getCheck_name() { + return check_name; + } + + public void setCheck_name(String check_name) { + this.check_name = check_name; + } + + public String getMchid() { + return mchid; + } + + public void setMchid(String mchid) { + this.mchid = mchid; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getPartner_trade_no() { + return partner_trade_no; + } + + public void setPartner_trade_no(String partner_trade_no) { + this.partner_trade_no = partner_trade_no; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + this.amount = amount; + } + + public String getDesc() { + return desc; + } + + public void setDesc(String desc) { + this.desc = desc; + } + + public Map<String, Object> toMap() { + Map<String, Object> map = new HashMap<String, Object>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + Object obj; + try { + obj = field.get(this); + if (obj != null) { + map.put(field.getName(), obj); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return map; + } +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/JsApiPayComResData.java b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayComResData.java new file mode 100644 index 0000000..5fc891b --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayComResData.java @@ -0,0 +1,207 @@ +package cc.mrbird.febs.pay.model; + +/** + * User: rizenguo + * Date: 2014/10/22 + * Time: 16:42 + */ + +/** + * 被扫支付提交Post数据给到API之后,API会返回XML格式的数据,这个类用来装这些数据 + */ +public class JsApiPayComResData { + //协议层 + private String return_code = ""; + private String return_msg = ""; + + //协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回) + private String mch_appid = ""; + private String mchid = ""; + private String nonce_str = ""; + //private String sign = ""; + private String result_code = ""; + private String err_code = ""; + private String err_code_des = ""; + + private String device_info = ""; + + //业务返回的具体数据(以下字段在return_code 和result_code 都为SUCCESS 的时候有返回) + private String payment_no = ""; + private String partner_trade_no = ""; + + private String payment_time=""; + + + + public String getReturn_code() { + return return_code; + } + + + + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + + + + public String getReturn_msg() { + return return_msg; + } + + + + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + + + + public String getMch_appid() { + return mch_appid; + } + + + public void setMch_appid(String mch_appid) { + this.mch_appid = mch_appid; + } + + + + public String getNonce_str() { + return nonce_str; + } + + + + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + + + + public String getResult_code() { + return result_code; + } + + + + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + + + + public String getErr_code() { + return err_code; + } + + + + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + + + + public String getErr_code_des() { + return err_code_des; + } + + + + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + + + + public String getDevice_info() { + return device_info; + } + + + + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + + + + public String getPayment_no() { + return payment_no; + } + + + + + public void setPayment_no(String payment_no) { + this.payment_no = payment_no; + } + + + + + public String getPartner_trade_no() { + return partner_trade_no; + } + + + + + public void setPartner_trade_no(String partner_trade_no) { + this.partner_trade_no = partner_trade_no; + } + + + + + public String getPayment_time() { + return payment_time; + } + + + + + public void setPayment_time(String payment_time) { + this.payment_time = payment_time; + } + + + + + public String getMchid() { + return mchid; + } + + + + + public void setMchid(String mchid) { + this.mchid = mchid; + } + + + + + @Override + public String toString() { + return "JsApiPayComResData [return_code=" + return_code + ", return_msg=" + return_msg + ", mch_appid=" + mch_appid + ", mchid=" + mchid + ", nonce_str=" + nonce_str + ", result_code=" + result_code + ", err_code=" + err_code + ", err_code_des=" + err_code_des + ", device_info=" + device_info + ", payment_no=" + payment_no + ", partner_trade_no=" + partner_trade_no + ", payment_time=" + payment_time + "]"; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/JsApiPayReqData.java b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayReqData.java new file mode 100644 index 0000000..1ab1b2f --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayReqData.java @@ -0,0 +1,298 @@ +package cc.mrbird.febs.pay.model; + + +import cc.mrbird.febs.pay.util.RandomStringGenerator; +import cc.mrbird.febs.pay.util.Signature; +import cc.mrbird.febs.pay.util.WechatConfigure; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * +* 预付订单请求参数 +* @author:姜友瑶 +* @date 2016年10月14日 + */ +public class JsApiPayReqData { + + //每个字段具体的意思请查看API文档 + private String appid = ""; + private String mch_id = ""; + private String device_info = ""; + private String nonce_str = ""; + private String sign = ""; + private String body = ""; + private String detail = ""; + private String attach = ""; + private String out_trade_no = ""; + private String fee_type = ""; + private int total_fee = 0; + /** + * 接收微信支付异步通知回调地址 + */ + private String trade_type = WechatConfigure.TRADE_TYPE_JSAPI; + private String notify_url ; + private String openid = ""; + private String limit_pay = ""; + private String spbill_create_ip = ""; + private String product_id = ""; + private String time_start = ""; + private String time_expire = ""; + private String goods_tag = ""; + private String auth_code = ""; + + + public JsApiPayReqData() { + } + + /**appID 收款应用id + * mchID 商户号 + * @param authCode 这个是扫码终端设备从用户手机上扫取到的支付授权号,这个号是跟用户用来支付的银行卡绑定的,有效期是1分钟 + * @param body 要支付的商品的描述信息,用户会在支付成功页面里看到这个信息 + * @param attach 支付订单里面可以填的附加数据,API会将提交的这个附加数据原样返回 + * @param outTradeNo 商户系统内部的订单号,32个字符内可包含字母, 确保在商户系统唯一 + * @param totalFee 订单总金额,单位为“分”,只能整数 + * @param deviceInfo 商户自己定义的扫码支付终端设备号,方便追溯这笔交易发生在哪台终端设备上 + * @param spBillCreateIP 订单生成的机器IP + * @param timeStart 订单生成时间, 格式为yyyyMMddHHmmss,如2009年12 月25 日9 点10 分10 秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器 + * @param timeExpire 订单失效时间,格式同上 + * @param goodsTag 商品标记,微信平台配置的商品标记,用于优惠券或者满减使用 + */ + public JsApiPayReqData(String appID, String mchID, String paySecret, String notify_url, String body, String outTradeNo, int totalFee, String spBillCreateIP, String openid, String attach){ + //默认必须设置 + setAppid(appID); + setMch_id(mchID); + setNotify_url(notify_url); + setBody(body); + setOut_trade_no(outTradeNo); + setTotal_fee(totalFee); + setSpbill_create_ip(spBillCreateIP); + setAttach(attach); + //随机字符串,不长于32 位 + setNonce_str(RandomStringGenerator.getRandomStringByLength(32)); + setOpenid(openid); + //根据API给的签名规则进行签名 【 必须要放在本方法的最后】 + String sign = Signature.getSign(toMap(),paySecret); + setSign(sign);//把签名数据设置到Sign这个属性中 + + } + + public JsApiPayReqData(String appID, String mchID, String paySecret, String notify_url, String body, String outTradeNo, int totalFee, String spBillCreateIP, String attach){ + //默认必须设置 + setAppid(appID); + setMch_id(mchID); + setBody(body); + setNotify_url(notify_url); + setOut_trade_no(outTradeNo); + setTotal_fee(totalFee); + setSpbill_create_ip(spBillCreateIP); + setAttach(attach); + //随机字符串,不长于32 位 + setNonce_str(RandomStringGenerator.getRandomStringByLength(32)); + //根据API给的签名规则进行签名 【 必须要放在本方法的最后】 + String sign = Signature.getSign(toMap(),paySecret); + setSign(sign);//把签名数据设置到Sign这个属性中 + } + + public String getDetail() { + return detail; + } + + public void setDetail(String detail) { + this.detail = detail; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public String getNotify_url() { + return notify_url; + } + + public void setNotify_url(String notify_url) { + this.notify_url = notify_url; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getLimit_pay() { + return limit_pay; + } + + public void setLimit_pay(String limit_pay) { + this.limit_pay = limit_pay; + } + + public String getProduct_id() { + return product_id; + } + + public void setProduct_id(String product_id) { + this.product_id = product_id; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getBody() { + return body; + } + + /** + * + * body最大长度128 + * @author:姜友瑶 + * @param body + * 返回类型 void + * @date 2016年10月13日 + */ + public void setBody(String body) { + + if(body.length()>128){ + body=body.substring(0, 128); + } + this.body = body; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public int getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(int total_fee) { + this.total_fee = total_fee; + } + + public String getSpbill_create_ip() { + return spbill_create_ip; + } + + public void setSpbill_create_ip(String spbill_create_ip) { + this.spbill_create_ip = spbill_create_ip; + } + + public String getTime_start() { + return time_start; + } + + public void setTime_start(String time_start) { + this.time_start = time_start; + } + + public String getTime_expire() { + return time_expire; + } + + public void setTime_expire(String time_expire) { + this.time_expire = time_expire; + } + + public String getGoods_tag() { + return goods_tag; + } + + public void setGoods_tag(String goods_tag) { + this.goods_tag = goods_tag; + } + + public String getAuth_code() { + return auth_code; + } + + public void setAuth_code(String auth_code) { + this.auth_code = auth_code; + } + + public Map<String,Object> toMap(){ + Map<String,Object> map = new HashMap<String, Object>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + Object obj; + try { + obj = field.get(this); + if(obj!=null){ + map.put(field.getName(), obj); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return map; + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/JsApiPayResData.java b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayResData.java new file mode 100644 index 0000000..37f36b9 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/JsApiPayResData.java @@ -0,0 +1,232 @@ +package cc.mrbird.febs.pay.model; + +/** + * User: rizenguo + * Date: 2014/10/22 + * Time: 16:42 + */ + +/** + * 被扫支付提交Post数据给到API之后,API会返回XML格式的数据,这个类用来装这些数据 + */ +public class JsApiPayResData { + //协议层 + private String return_code = ""; + private String return_msg = ""; + + //协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回) + private String appid = ""; + private String mch_id = ""; + private String nonce_str = ""; + private String sign = ""; + private String result_code = ""; + private String err_code = ""; + private String err_code_des = ""; + + private String device_info = ""; + + //业务返回的具体数据(以下字段在return_code 和result_code 都为SUCCESS 的时候有返回) + private String openid = ""; + private String is_subscribe = ""; + private String trade_type = ""; + private String bank_type = ""; + private String total_fee = ""; + private String coupon_fee = ""; + private String fee_type = ""; + private String transaction_id = ""; + private String out_trade_no = ""; + private String attach = ""; + private String time_end = ""; + private String prepay_id = ""; + + + + public String getPrepay_id() { + return prepay_id; + } + + public void setPrepay_id(String prepay_id) { + this.prepay_id = prepay_id; + } + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getIs_subscribe() { + return is_subscribe; + } + + public void setIs_subscribe(String is_subscribe) { + this.is_subscribe = is_subscribe; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getBank_type() { + return bank_type; + } + + public void setBank_type(String bank_type) { + this.bank_type = bank_type; + } + + public String getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(String total_fee) { + this.total_fee = total_fee; + } + + public String getCoupon_fee() { + return coupon_fee; + } + + public void setCoupon_fee(String coupon_fee) { + this.coupon_fee = coupon_fee; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getTime_end() { + return time_end; + } + + public void setTime_end(String time_end) { + this.time_end = time_end; + } + + @Override + public String toString() { + return "JsApiPayResData [return_code=" + return_code + ", return_msg=" + return_msg + ", appid=" + appid + + ", mch_id=" + mch_id + ", nonce_str=" + nonce_str + ", sign=" + sign + ", result_code=" + result_code + + ", err_code=" + err_code + ", err_code_des=" + err_code_des + ", device_info=" + device_info + + ", openid=" + openid + ", is_subscribe=" + is_subscribe + ", trade_type=" + trade_type + + ", bank_type=" + bank_type + ", total_fee=" + total_fee + ", coupon_fee=" + coupon_fee + ", fee_type=" + + fee_type + ", transaction_id=" + transaction_id + ", out_trade_no=" + out_trade_no + ", attach=" + + attach + ", time_end=" + time_end + ", prepay_id=" + prepay_id + "]"; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/NotifyData.java b/src/main/java/cc/mrbird/febs/pay/model/NotifyData.java new file mode 100644 index 0000000..924e96e --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/NotifyData.java @@ -0,0 +1,145 @@ +package cc.mrbird.febs.pay.model; + +/** + * User: rizenguo + * Date: 2014/10/25 + * Time: 13:54 + */ +public class NotifyData { + + private String appid = ""; + private String bank_type = ""; + private String cash_fee = ""; + private String fee_type = ""; + private String is_subscribe = ""; + private String mch_id = ""; + private String nonce_str = ""; + private String openid = ""; + private String out_trade_no = ""; + private String result_code = ""; + private String return_code = ""; + private String sign = ""; + private String attach = ""; + private String time_end = ""; + private String total_fee = ""; + private String trade_type = ""; + private String transaction_id = ""; + + + + public String getAttach() { + return attach; + } + public void setAttach(String attach) { + this.attach = attach; + } + public String getAppid() { + return appid; + } + public void setAppid(String appid) { + this.appid = appid; + } + public String getBank_type() { + return bank_type; + } + public void setBank_type(String bank_type) { + this.bank_type = bank_type; + } + public String getCash_fee() { + return cash_fee; + } + public void setCash_fee(String cash_fee) { + this.cash_fee = cash_fee; + } + public String getFee_type() { + return fee_type; + } + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + public String getIs_subscribe() { + return is_subscribe; + } + public void setIs_subscribe(String is_subscribe) { + this.is_subscribe = is_subscribe; + } + public String getMch_id() { + return mch_id; + } + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + public String getNonce_str() { + return nonce_str; + } + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + public String getOpenid() { + return openid; + } + public void setOpenid(String openid) { + this.openid = openid; + } + public String getOut_trade_no() { + return out_trade_no; + } + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + public String getResult_code() { + return result_code; + } + public void setResult_code(String result_code) { + this.result_code = result_code; + } + public String getReturn_code() { + return return_code; + } + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + public String getSign() { + return sign; + } + public void setSign(String sign) { + this.sign = sign; + } + public String getTime_end() { + return time_end; + } + public void setTime_end(String time_end) { + this.time_end = time_end; + } + public String getTotal_fee() { + return total_fee; + } + public void setTotal_fee(String total_fee) { + this.total_fee = total_fee; + } + public String getTrade_type() { + return trade_type; + } + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + public String getTransaction_id() { + return transaction_id; + } + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + + @Override + public String toString() { + + return "{appid:"+appid+","+"cash_fee:"+cash_fee + +","+"result_code:"+result_code+","+"openid:"+openid + +","+"total_fee:"+total_fee + +","+"attach:"+attach + +","+"transaction_id:"+transaction_id + +","+"out_trade_no:"+out_trade_no+"}"; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/RefundReqData.java b/src/main/java/cc/mrbird/febs/pay/model/RefundReqData.java new file mode 100644 index 0000000..83c86db --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/RefundReqData.java @@ -0,0 +1,192 @@ +package cc.mrbird.febs.pay.model; + + +import cc.mrbird.febs.pay.util.RandomStringGenerator; +import cc.mrbird.febs.pay.util.Signature; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * User: rizenguo + * Date: 2014/10/25 + * Time: 16:12 + */ +public class RefundReqData { + + //每个字段具体的意思请查看API文档 + private String appid = ""; + private String mch_id = ""; + private String device_info = ""; + private String nonce_str = ""; + private String sign = ""; + private String transaction_id = ""; + private String out_trade_no = ""; + private String out_refund_no = ""; + private int total_fee = 0; + private int refund_fee = 0; + private String refund_fee_type = "CNY"; + private String op_user_id = ""; + + /** + * 请求退款服务 + * @param transactionID 是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。建议优先使用 + * @param outTradeNo 商户系统内部的订单号,transaction_id 、out_trade_no 二选一,如果同时存在优先级:transaction_id>out_trade_no + * @param deviceInfo 微信支付分配的终端设备号,与下单一致 + * @param outRefundNo 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔 + * @param totalFee 订单总金额,单位为分 + * @param refundFee 退款总金额,单位为分,可以做部分退款 + * @param opUserID 操作员帐号, 默认为商户号 + * @param refundFeeType 货币类型,符合ISO 4217标准的三位字母代码,默认为CNY(人民币) + */ + public RefundReqData(String mchID,String appID,String paySecret ,String outTradeNo,String outRefundNo,int totalFee,int refundFee,String opUserID){ + + //微信分配的公众号ID(开通公众号之后可以获取到) + setAppid(appID); + + //微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到) + setMch_id(mchID); + + //transaction_id是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。 + //setTransaction_id(transactionID); + + //商户系统自己生成的唯一的订单号 + setOut_trade_no(outTradeNo); + + //微信支付分配的终端设备号,与下单一致 + //setDevice_info(deviceInfo); + + setOut_refund_no(outRefundNo); + + setTotal_fee(totalFee); + + setRefund_fee(refundFee); + + setOp_user_id(opUserID); + + //随机字符串,不长于32 位 + setNonce_str(RandomStringGenerator.getRandomStringByLength(32)); + + //根据API给的签名规则进行签名 + String sign = Signature.getSign(toMap(),paySecret); + setSign(sign);//把签名数据设置到Sign这个属性中 + + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getOut_refund_no() { + return out_refund_no; + } + + public void setOut_refund_no(String out_refund_no) { + this.out_refund_no = out_refund_no; + } + + public int getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(int total_fee) { + this.total_fee = total_fee; + } + + public int getRefund_fee() { + return refund_fee; + } + + public void setRefund_fee(int refund_fee) { + this.refund_fee = refund_fee; + } + + public String getOp_user_id() { + return op_user_id; + } + + public void setOp_user_id(String op_user_id) { + this.op_user_id = op_user_id; + } + + public String getRefund_fee_type() { + return refund_fee_type; + } + + public void setRefund_fee_type(String refund_fee_type) { + this.refund_fee_type = refund_fee_type; + } + + public Map<String,Object> toMap(){ + Map<String,Object> map = new HashMap<String, Object>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + Object obj; + try { + obj = field.get(this); + if(obj!=null){ + map.put(field.getName(), obj); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return map; + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/RefundResData.java b/src/main/java/cc/mrbird/febs/pay/model/RefundResData.java new file mode 100644 index 0000000..03b7e50 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/RefundResData.java @@ -0,0 +1,168 @@ +package cc.mrbird.febs.pay.model; + +/** + * User: rizenguo + * Date: 2014/10/25 + * Time: 16:12 + */ +public class RefundResData { + + //协议层 + private String return_code = ""; + private String return_msg = ""; + + //协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回) + private String appid = ""; + private String mch_id = ""; + private String sub_mch_id = ""; + private String device_info = ""; + private String nonce_str = ""; + private String sign = ""; + private String result_code = ""; + private String err_code = ""; + private String err_code_des = ""; + + + private String transaction_id = ""; + private String out_trade_no = ""; + private String out_refund_no = ""; + private String refund_id = ""; + private String refund_fee = ""; + private String coupon_refund_fee = ""; + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getSub_mch_id() { + return sub_mch_id; + } + + public void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getOut_refund_no() { + return out_refund_no; + } + + public void setOut_refund_no(String out_refund_no) { + this.out_refund_no = out_refund_no; + } + + public String getRefund_id() { + return refund_id; + } + + public void setRefund_id(String refund_id) { + this.refund_id = refund_id; + } + + public String getRefund_fee() { + return refund_fee; + } + + public void setRefund_fee(String refund_fee) { + this.refund_fee = refund_fee; + } + + public String getCoupon_refund_fee() { + return coupon_refund_fee; + } + + public void setCoupon_refund_fee(String coupon_refund_fee) { + this.coupon_refund_fee = coupon_refund_fee; + } +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryReqData.java b/src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryReqData.java new file mode 100644 index 0000000..3ec8c1d --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryReqData.java @@ -0,0 +1,125 @@ +package cc.mrbird.febs.pay.model; + +import cc.mrbird.febs.pay.util.RandomStringGenerator; + +import java.lang.reflect.Field; +import java.util.HashMap; +import java.util.Map; + +/** + * User: rizenguo + * Date: 2014/10/25 + * Time: 13:54 + */ +public class ScanPayQueryReqData { + + //每个字段具体的意思请查看API文档 + private String appid = ""; + private String mch_id = ""; + private String transaction_id = ""; + private String out_trade_no = ""; + private String nonce_str = ""; + private String sign = ""; + + /** + * 请求支付查询服务 + * @param transactionID 是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。建议优先使用 + * @param outTradeNo 商户系统内部的订单号,transaction_id 、out_trade_no 二选一,如果同时存在优先级:transaction_id>out_trade_no + * @return API返回的XML数据 + * @throws Exception + */ + public ScanPayQueryReqData(String transactionID, String outTradeNo){ + + //-------------------------------------------------------------------- + //以下是测试数据,请商户按照自己的实际情况填写具体的值进去 + //-------------------------------------------------------------------- + + //微信分配的公众号ID(开通公众号之后可以获取到) + //setAppid(WechatConfigure.appID); + + //微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到) + // setMch_id(WechatConfigure.mchID); + + //transaction_id是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。 + setTransaction_id(transactionID); + + //商户系统自己生成的唯一的订单号 + setOut_trade_no(outTradeNo); + + //随机字符串,不长于32 位 + setNonce_str(RandomStringGenerator.getRandomStringByLength(32)); + + //根据API给的签名规则进行签名 + //String sign = Signature.getSign(toMap()); + setSign(sign);//把签名数据设置到Sign这个属性中 + + + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public Map<String,Object> toMap(){ + Map<String,Object> map = new HashMap<String, Object>(); + Field[] fields = this.getClass().getDeclaredFields(); + for (Field field : fields) { + Object obj; + try { + obj = field.get(this); + if(obj!=null){ + map.put(field.getName(), obj); + } + } catch (IllegalArgumentException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + } + return map; + } +} diff --git a/src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryResData.java b/src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryResData.java new file mode 100644 index 0000000..29b935d --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/model/ScanPayQueryResData.java @@ -0,0 +1,236 @@ +package cc.mrbird.febs.pay.model; + +/** + * User: rizenguo + * Date: 2014/10/25 + * Time: 13:54 + */ +public class ScanPayQueryResData { + + //协议层 + private String return_code = ""; + private String return_msg = ""; + + //协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回) + private String appid = ""; + private String mch_id = ""; + private String sub_mch_id = "";//新增 + private String nonce_str = ""; + private String sign = ""; + private String result_code = ""; + private String err_code = ""; + private String err_code_des = ""; + + //以下字段在return_code 和result_code 都为SUCCESS 的时候有返回 + private String trade_state = ""; + + //trade_state的几种可能取值: + // SUCCESS--支付成功 + // REFUND--转入退款 + // NOTPAY--未支付 + // CLOSED--已关闭 + // REVOKED--已撤销 + // USERPAYING--用户支付中 + // NOPAY--未支付(确认支付超时) + // PAYERROR--支付失败(其他原因, + // 如银行返回失败) + + //以下字段在trade_state 为SUCCESS 或者REFUND 的时候有返回 + private String device_info = ""; + private String openid = ""; + private String is_subscribe = ""; + private String trade_type = ""; + private String bank_type = ""; + private String total_fee = ""; + private String coupon_fee = ""; + private String fee_type = ""; + private String transaction_id = ""; + private String out_trade_no = ""; + private String attach = ""; + private String time_end = ""; + + public String getReturn_code() { + return return_code; + } + + public void setReturn_code(String return_code) { + this.return_code = return_code; + } + + public String getReturn_msg() { + return return_msg; + } + + public void setReturn_msg(String return_msg) { + this.return_msg = return_msg; + } + + public String getAppid() { + return appid; + } + + public void setAppid(String appid) { + this.appid = appid; + } + + public String getMch_id() { + return mch_id; + } + + public void setMch_id(String mch_id) { + this.mch_id = mch_id; + } + + public String getSub_mch_id() { + return sub_mch_id; + } + + public void setSub_mch_id(String sub_mch_id) { + this.sub_mch_id = sub_mch_id; + } + + public String getNonce_str() { + return nonce_str; + } + + public void setNonce_str(String nonce_str) { + this.nonce_str = nonce_str; + } + + public String getSign() { + return sign; + } + + public void setSign(String sign) { + this.sign = sign; + } + + public String getResult_code() { + return result_code; + } + + public void setResult_code(String result_code) { + this.result_code = result_code; + } + + public String getErr_code() { + return err_code; + } + + public void setErr_code(String err_code) { + this.err_code = err_code; + } + + public String getErr_code_des() { + return err_code_des; + } + + public void setErr_code_des(String err_code_des) { + this.err_code_des = err_code_des; + } + + public String getTrade_state() { + return trade_state; + } + + public void setTrade_state(String trade_state) { + this.trade_state = trade_state; + } + + public String getDevice_info() { + return device_info; + } + + public void setDevice_info(String device_info) { + this.device_info = device_info; + } + + public String getOpenid() { + return openid; + } + + public void setOpenid(String openid) { + this.openid = openid; + } + + public String getIs_subscribe() { + return is_subscribe; + } + + public void setIs_subscribe(String is_subscribe) { + this.is_subscribe = is_subscribe; + } + + public String getTrade_type() { + return trade_type; + } + + public void setTrade_type(String trade_type) { + this.trade_type = trade_type; + } + + public String getBank_type() { + return bank_type; + } + + public void setBank_type(String bank_type) { + this.bank_type = bank_type; + } + + public String getTotal_fee() { + return total_fee; + } + + public void setTotal_fee(String total_fee) { + this.total_fee = total_fee; + } + + public String getCoupon_fee() { + return coupon_fee; + } + + public void setCoupon_fee(String coupon_fee) { + this.coupon_fee = coupon_fee; + } + + public String getFee_type() { + return fee_type; + } + + public void setFee_type(String fee_type) { + this.fee_type = fee_type; + } + + public String getTransaction_id() { + return transaction_id; + } + + public void setTransaction_id(String transaction_id) { + this.transaction_id = transaction_id; + } + + public String getOut_trade_no() { + return out_trade_no; + } + + public void setOut_trade_no(String out_trade_no) { + this.out_trade_no = out_trade_no; + } + + public String getAttach() { + return attach; + } + + public void setAttach(String attach) { + this.attach = attach; + } + + public String getTime_end() { + return time_end; + } + + public void setTime_end(String time_end) { + this.time_end = time_end; + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/IServiceRequest.java b/src/main/java/cc/mrbird/febs/pay/service/IServiceRequest.java new file mode 100644 index 0000000..d7aa441 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/IServiceRequest.java @@ -0,0 +1,20 @@ +package cc.mrbird.febs.pay.service; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; + +/** + * User: rizenguo + * Date: 2014/12/10 + * Time: 15:16 + * 这里定义服务层需要请求器标准接口 + */ +public interface IServiceRequest { + + //Service依赖的底层https请求器必须实现这么一个接口 + public String sendPost(String api_url, Object xmlObj) throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, IOException; + +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/IXcxPayService.java b/src/main/java/cc/mrbird/febs/pay/service/IXcxPayService.java new file mode 100644 index 0000000..a55f404 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/IXcxPayService.java @@ -0,0 +1,12 @@ +package cc.mrbird.febs.pay.service; + +import cc.mrbird.febs.mall.entity.MallOrderInfo; +import cc.mrbird.febs.pay.model.BrandWCPayRequestData; + +public interface IXcxPayService { + + /** + * 发起支付(创建预付订单) + */ + BrandWCPayRequestData startPayment(MallOrderInfo mallOrderInfo) throws Exception; +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/BaseService.java b/src/main/java/cc/mrbird/febs/pay/service/impl/BaseService.java new file mode 100644 index 0000000..1ffc61e --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/impl/BaseService.java @@ -0,0 +1,47 @@ +package cc.mrbird.febs.pay.service.impl; + +import cc.mrbird.febs.pay.service.IServiceRequest; + +import java.io.IOException; +import java.security.KeyManagementException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.UnrecoverableKeyException; + +/** + * User: rizenguo + * Date: 2014/12/10 + * Time: 15:44 + * 服务的基类 + */ +public class BaseService { + + //API的地址 + private String apiURL; + + //发请求的HTTPS请求器 + private IServiceRequest serviceRequest; + + public BaseService(String api, String HttpsRequestClassName) throws ClassNotFoundException, IllegalAccessException, InstantiationException { + apiURL = api; + Class<?> c = Class.forName(HttpsRequestClassName); + serviceRequest = (IServiceRequest) c.newInstance(); + } + + protected String sendPost(Object xmlObj) throws UnrecoverableKeyException, IOException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException { + return serviceRequest.sendPost(apiURL,xmlObj); + } + + + /** + * 供商户想自定义自己的HTTP请求器用 + * @param request 实现了IserviceRequest接口的HttpsRequest + */ + public void setServiceRequest(IServiceRequest request){ + serviceRequest = request; + } + + public IServiceRequest getServiceRequest() { + return serviceRequest; + } +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayComService.java b/src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayComService.java new file mode 100644 index 0000000..693dd88 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayComService.java @@ -0,0 +1,34 @@ +package cc.mrbird.febs.pay.service.impl; + + +import cc.mrbird.febs.pay.model.JsApiPayComReqData; +import cc.mrbird.febs.pay.util.WechatConfigure; + +/** + * User: rizenguo + * Date: 2014/10/29 + * Time: 16:04 + */ +public class JsApiPayComService extends BaseService{ + + public JsApiPayComService() throws IllegalAccessException, InstantiationException, ClassNotFoundException { + super(WechatConfigure.COM_PAY_API, WechatConfigure.HttpsRequestClassName2); + } + + /** + * 请求支付查询服务 + * @return API返回的XML数据 + * @throws Exception + */ + public String request(JsApiPayComReqData jsApiPayComReqData) throws Exception { + + //-------------------------------------------------------------------- + //发送HTTPS的Post请求到API地址 + //-------------------------------------------------------------------- + String responseString = sendPost(jsApiPayComReqData); + + return responseString; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayService.java b/src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayService.java new file mode 100644 index 0000000..4706b11 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/impl/JsApiPayService.java @@ -0,0 +1,55 @@ +package cc.mrbird.febs.pay.service.impl; + + +import cc.mrbird.febs.pay.model.JsApiPayReqData; +import cc.mrbird.febs.pay.util.WechatConfigure; + +/** + * User: rizenguo + * Date: 2014/10/29 + * Time: 16:03 + */ +public class JsApiPayService extends BaseService{ + + public JsApiPayService() throws Exception { + super(WechatConfigure.UNIFIEDORDER, WechatConfigure.HttpsRequestClassName); + } + + /** + * 请求支付服务 + * @param jsApiPayReqData 这个数据对象里面包含了API要求提交的各种数据字段 + * @return API返回的数据 + * @throws Exception + */ + public String request(JsApiPayReqData jsApiPayReqData) throws Exception { + + //-------------------------------------------------------------------- + //发送HTTPS的Post请求到API地址 + //-------------------------------------------------------------------- + String responseString = sendPost(jsApiPayReqData); + + return responseString; + } + + + + + /** + * 请求openid + * @param + * @return API返回的数据 + * @throws Exception + */ + public String requestOpenid(JsApiPayReqData jsApiPayReqData) throws Exception { + + //-------------------------------------------------------------------- + //发送HTTPS的Post请求到API地址 + //-------------------------------------------------------------------- + String responseString = sendPost(jsApiPayReqData); + + return responseString; + } + + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/RefundService.java b/src/main/java/cc/mrbird/febs/pay/service/impl/RefundService.java new file mode 100644 index 0000000..d98c3c8 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/impl/RefundService.java @@ -0,0 +1,33 @@ +package cc.mrbird.febs.pay.service.impl; + +import cc.mrbird.febs.pay.model.RefundReqData; +import cc.mrbird.febs.pay.util.WechatConfigure; + +/** + * User: rizenguo + * Date: 2014/10/29 + * Time: 16:04 + */ +public class RefundService extends BaseService{ + + public RefundService() throws IllegalAccessException, InstantiationException, ClassNotFoundException { + super(WechatConfigure.REFUND_API, WechatConfigure.HttpsRequestClassName2); + } + + /** + * 请求支付查询服务 + * @return API返回的XML数据 + * @throws Exception + */ + public String request(RefundReqData refundReqData) throws Exception { + + //-------------------------------------------------------------------- + //发送HTTPS的Post请求到API地址 + //-------------------------------------------------------------------- + String responseString = sendPost(refundReqData); + + return responseString; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/ScanPayQueryService.java b/src/main/java/cc/mrbird/febs/pay/service/impl/ScanPayQueryService.java new file mode 100644 index 0000000..cd9a1b6 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/impl/ScanPayQueryService.java @@ -0,0 +1,29 @@ +package cc.mrbird.febs.pay.service.impl; + +import cc.mrbird.febs.pay.model.ScanPayQueryReqData; +import cc.mrbird.febs.pay.util.WechatConfigure; + +public class ScanPayQueryService extends BaseService{ + + public ScanPayQueryService() throws IllegalAccessException, InstantiationException, ClassNotFoundException { + super(WechatConfigure.PAY_QUERY_API, WechatConfigure.HttpsRequestClassName); + } + + /** + * 请求支付查询服务 + * @param scanPayQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段 + * @return API返回的XML数据 + * @throws Exception + */ + public String request(ScanPayQueryReqData scanPayQueryReqData) throws Exception { + + //-------------------------------------------------------------------- + //发送HTTPS的Post请求到API地址 + //-------------------------------------------------------------------- + String responseString = sendPost(scanPayQueryReqData); + + return responseString; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java b/src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java new file mode 100644 index 0000000..6ee06f2 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/service/impl/XcxPayServiceImpl.java @@ -0,0 +1,93 @@ +package cc.mrbird.febs.pay.service.impl; + +import cc.mrbird.febs.common.properties.XcxProperties; +import cc.mrbird.febs.common.utils.SpringContextHolder; +import cc.mrbird.febs.mall.entity.MallMember; +import cc.mrbird.febs.mall.entity.MallOrderInfo; +import cc.mrbird.febs.mall.entity.MallOrderItem; +import cc.mrbird.febs.mall.mapper.MallMemberMapper; +import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper; +import cc.mrbird.febs.pay.model.BrandWCPayRequestData; +import cc.mrbird.febs.pay.service.IXcxPayService; +import cc.mrbird.febs.pay.util.WeixinServiceUtil; +import cn.hutool.log.Log; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.math.BigDecimal; +import java.util.List; + +@Slf4j +@Service +public class XcxPayServiceImpl implements IXcxPayService { + + @Autowired + MallOrderInfoMapper mallOrderInfoMapper; + @Autowired + MallMemberMapper mallMemberMapper; + @Autowired + WeixinServiceUtil weixinServiceUtil; + + private final XcxProperties xcxProperties = SpringContextHolder.getBean(XcxProperties.class); + + @Override + public BrandWCPayRequestData startPayment(MallOrderInfo mallOrderInfo) throws Exception { + BigDecimal unit = new BigDecimal("100"); + BigDecimal money = new BigDecimal(mallOrderInfo.getAmount().toString()); + BrandWCPayRequestData payData; + String productNames = getProductNames(mallOrderInfo.getMemberId(), mallOrderInfo.getId()); + MallMember mallMember = mallMemberMapper.selectById(mallOrderInfo.getMemberId()); + Boolean debug = xcxProperties.getDebug(); + if (debug) { + payData = weixinServiceUtil.createOrder("[测试]" + productNames, mallOrderInfo.getOrderNo(), + 1, mallMember.getOpenId(), String.valueOf(mallOrderInfo.getId())); + } else { + payData = weixinServiceUtil.createOrder(productNames, mallOrderInfo.getOrderNo(), + unit.multiply(money).intValue(),mallMember.getOpenId(), String.valueOf(mallOrderInfo.getId())); + } + mallOrderInfo.setWxOrderNo(payData.getPrepay_id()); + mallOrderInfoMapper.updateById(mallOrderInfo); + return payData; + } + + /** + * 根据用户ID和订单ID获取所购买商品名称 + * @return 所含商品名称(多个以","隔开) + */ + public String getProductNames(Long memberId, Long orderId) { + MallOrderInfo mallOrderInfo = mallOrderInfoMapper.selectOrderByMemberIdAndId(memberId, orderId); + List<MallOrderItem> details = mallOrderInfo.getItems(); + if (CollectionUtils.isEmpty(details)) { + return ""; + } + StringBuffer productNameBuffer = new StringBuffer(); + Integer maxLength = 30; + for (int i = 0; i< details.size(); i++) { + MallOrderItem mallOrderItem = details.get(i); + String goodsName = mallOrderItem.getGoodsName(); + if (goodsName == null) { + continue; + } + if (i == 0 && goodsName.length() > maxLength) { + productNameBuffer.append(goodsName.substring(0, maxLength) + "..."); + break; + } + if ((productNameBuffer.length() + goodsName.length()) > maxLength) { + productNameBuffer.append("等"); + break; + } + productNameBuffer.append(goodsName + ","); + } + String productNames = productNameBuffer.toString(); + if (productNames.endsWith(",")) { + productNames = productNames.substring(0, productNames.length() - 1); + } + if (productNames.endsWith(",等")) { + productNames = productNames.substring(0, productNames.length() - 2) + "等"; + } + return productNames; + } +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/MD5.java b/src/main/java/cc/mrbird/febs/pay/util/MD5.java new file mode 100644 index 0000000..b9d8357 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/MD5.java @@ -0,0 +1,59 @@ +package cc.mrbird.febs.pay.util; + +import java.security.MessageDigest; + +/** + * User: rizenguo + * Date: 2014/10/23 + * Time: 15:43 + */ +public class MD5 { + private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7", + "8", "9", "a", "b", "c", "d", "e", "f"}; + + /** + * 转换字节数组为16进制字串 + * @param b 字节数组 + * @return 16进制字串 + */ + public static String byteArrayToHexString(byte[] b) { + StringBuilder resultSb = new StringBuilder(); + for (byte aB : b) { + resultSb.append(byteToHexString(aB)); + } + return resultSb.toString(); + } + + /** + * 转换byte到16进制 + * @param b 要转换的byte + * @return 16进制格式 + */ + private static String byteToHexString(byte b) { + int n = b; + if (n < 0) { + n = 256 + n; + } + int d1 = n / 16; + int d2 = n % 16; + return hexDigits[d1] + hexDigits[d2]; + } + + /** + * MD5编码 + * @param origin 原始字符串 + * @return 经过MD5加密之后的结果 + */ + public static String MD5Encode(String origin) { + String resultString = null; + try { + resultString = origin; + MessageDigest md = MessageDigest.getInstance("MD5"); + resultString = byteArrayToHexString(md.digest(resultString.getBytes("utf-8"))); + } catch (Exception e) { + e.printStackTrace(); + } + return resultString; + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/PayThreadPool.java b/src/main/java/cc/mrbird/febs/pay/util/PayThreadPool.java new file mode 100644 index 0000000..db5f551 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/PayThreadPool.java @@ -0,0 +1,46 @@ +package cc.mrbird.febs.pay.util; + +import cc.mrbird.febs.common.entity.FebsResponse; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.Map; + +@Slf4j +public class PayThreadPool { + + private static Map<Integer, Object> PAY_WAIT_POOL = new HashMap<>(); + private static Map<Integer, FebsResponse> PAY_THREAD_MSG = new HashMap<>(); + + public static void waitThread(Integer orderId, Object lock) { + PAY_WAIT_POOL.put(orderId, lock); + synchronized (lock) { + try { + // 设置线程最多等待15s + lock.wait(1000 * 15); + } catch (InterruptedException e) { + log.debug("线程等待失败", e); + } + } + + } + + public static FebsResponse getThreadResult(Integer orderId) { + //获取一次后删除结果对象 + // TODO 需要优化可能存在对象积压过多内存溢出风险 + return PAY_THREAD_MSG.remove(orderId); + } + + public static void notifyThread(Integer orderId, FebsResponse result) { + Object lock = PAY_WAIT_POOL.get(orderId); + if (lock != null) { + synchronized (lock) { + log.debug("尝试释放锁{}", orderId); + PAY_THREAD_MSG.put(orderId, result); + PAY_WAIT_POOL.remove(orderId); + lock.notifyAll(); + } + } + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/RandomStringGenerator.java b/src/main/java/cc/mrbird/febs/pay/util/RandomStringGenerator.java new file mode 100644 index 0000000..c9b77ea --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/RandomStringGenerator.java @@ -0,0 +1,23 @@ +package cc.mrbird.febs.pay.util; + +import java.util.Random; + +public class RandomStringGenerator { + + /** + * 获取一定长度的随机字符串 + * @param length 指定字符串长度 + * @return 一定长度的字符串 + */ + public static String getRandomStringByLength(int length) { + String base = "abcdefghijklmnopqrstuvwxyz0123456789"; + Random random = new Random(); + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < length; i++) { + int number = random.nextInt(base.length()); + sb.append(base.charAt(number)); + } + return sb.toString(); + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/Signature.java b/src/main/java/cc/mrbird/febs/pay/util/Signature.java new file mode 100644 index 0000000..5284337 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/Signature.java @@ -0,0 +1,144 @@ +package cc.mrbird.febs.pay.util; + +import org.apache.commons.codec.digest.DigestUtils; +import org.xml.sax.SAXException; + +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Map; + +/** + * User: rizenguo Date: 2014/10/29 Time: 15:23 + */ +public class Signature { + /** + * 签名算法 + * + * @param o + * 要参与签名的数据对象 + * @return 签名 + * @throws IllegalAccessException + */ + public static String getSign(Object o,String paySecret) throws IllegalAccessException { + ArrayList<String> list = new ArrayList<String>(); + Class<? extends Object> cls = o.getClass(); + Field[] fields = cls.getDeclaredFields(); + for (Field f : fields) { + f.setAccessible(true); + if (f.get(o) != null && f.get(o) != "") { + list.add(f.getName() + "=" + f.get(o) + "&"); + } + } + int size = list.size(); + String[] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + sb.append(arrayToSort[i]); + } + String result = sb.toString(); + result += "key=" +paySecret; + Util.log("Sign Before MD5:" + result); + result = MD5.MD5Encode(result).toUpperCase(); + Util.log("Sign Result:" + result); + return result; + } + + public static String getSign(Map<String, Object> map,String paySecret) { + ArrayList<String> list = new ArrayList<String>(); + for (Map.Entry<String, Object> entry : map.entrySet()) { + if (entry.getValue() != "") { + list.add(entry.getKey() + "=" + entry.getValue() + "&"); + } + } + int size = list.size(); + String[] arrayToSort = list.toArray(new String[size]); + Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < size; i++) { + sb.append(arrayToSort[i]); + } + String result = sb.toString(); + result += "key=" + paySecret; + Util.log("Sign Before MD5:" + result); + result = MD5.MD5Encode(result).toUpperCase(); + Util.log("Sign Result:" + result); + return result; + } + + /** + * 从API返回的XML数据里面重新计算一次签名 + * + * @param responseString + * API返回的XML数据 + * @return 新鲜出炉的签名 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static String getSignFromResponseString(String responseString,String paySecret) + throws IOException, SAXException, ParserConfigurationException { + Map<String, Object> map = XMLParser.getMapFromXML(responseString); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + map.put("sign", ""); + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 + return Signature.getSign(map,paySecret); + } + + /** + * 检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改 + * + * @param responseString + * API返回的XML数据字符串 + * @return API签名是否合法 + * @throws ParserConfigurationException + * @throws IOException + * @throws SAXException + */ + public static boolean checkIsSignValidFromResponseString(String responseString,String paySecret) + throws ParserConfigurationException, IOException, SAXException { + + Map<String, Object> map = XMLParser.getMapFromXML(responseString); + Util.log(map.toString()); + + String signFromAPIResponse = map.get("sign").toString(); + if (signFromAPIResponse == "" || signFromAPIResponse == null) { + Util.log("API返回的数据签名数据不存在,有可能被第三方篡改!!!"); + return false; + } + Util.log("服务器回包里面的签名是:" + signFromAPIResponse); + // 清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名 + map.put("sign", ""); + // 将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较 + String signForAPIResponse = Signature.getSign(map,paySecret); + + if (!signForAPIResponse.equals(signFromAPIResponse)) { + // 签名验不过,表示这个API返回的数据有可能已经被篡改了 + Util.log("API返回的数据签名验证不通过,有可能被第三方篡改!!!"); + return false; + } + Util.log("恭喜,API返回的数据签名验证通过!!!"); + return true; + } + + + + /** + * + * JS-SDK权限验证的签名 + * @author:姜友瑶 + * 返回类型 void + * @date 2016年10月18日 + */ + public static String getJsSdkSign(String jsapi_ticket,String noncestr,String timestamp,String url) { + String string1="jsapi_ticket="+jsapi_ticket+"&noncestr="+noncestr+"×tamp="+timestamp+"&url="+url; + Util.log("Sign Before sha1Hex:" + string1); + String signature= DigestUtils.sha1Hex(string1); + Util.log("Sign Before sha1Hex:" + signature); + return signature; + } + +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/Util.java b/src/main/java/cc/mrbird/febs/pay/util/Util.java new file mode 100644 index 0000000..fce911a --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/Util.java @@ -0,0 +1,119 @@ +package cc.mrbird.febs.pay.util; + +import com.thoughtworks.xstream.XStream; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.Field; +import java.util.Map; + +/** + * User: rizenguo + * Date: 2014/10/23 + * Time: 14:59 + */ +public class Util { + + //打log用 + + /** + * 通过反射的方式遍历对象的属性和属性值,方便调试 + * + * @param o 要遍历的对象 + * @throws Exception + */ + public static void reflect(Object o) throws Exception { + Class<? extends Object> cls = o.getClass(); + Field[] fields = cls.getDeclaredFields(); + for (int i = 0; i < fields.length; i++) { + Field f = fields[i]; + f.setAccessible(true); + Util.log(f.getName() + " -> " + f.get(o)); + } + } + + public static byte[] readInput(InputStream in) throws IOException { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + int len = 0; + byte[] buffer = new byte[1024]; + while ((len = in.read(buffer)) > 0) { + out.write(buffer, 0, len); + } + out.close(); + in.close(); + return out.toByteArray(); + } + + public static String inputStreamToString(InputStream is) throws IOException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + int i; + while ((i = is.read()) != -1) { + baos.write(i); + } + return baos.toString(); + } + + + public static InputStream getStringStream(String sInputString) { + ByteArrayInputStream tInputStringStream = null; + if (sInputString != null && !sInputString.trim().equals("")) { + tInputStringStream = new ByteArrayInputStream(sInputString.getBytes()); + } + return tInputStringStream; + } + + public static Object getObjectFromXML(String xml, Class<?> tClass) { + //将从API返回的XML数据映射到Java对象 + XStream xStreamForResponseData = new XStream(); + XStream.setupDefaultSecurity(xStreamForResponseData); + xStreamForResponseData.allowTypes(new Class[]{tClass}); + xStreamForResponseData.alias("xml", tClass); + xStreamForResponseData.ignoreUnknownElements();//暂时忽略掉一些新增的字段 + return xStreamForResponseData.fromXML(xml); + } + + public static String getStringFromMap(Map<String, Object> map, String key, String defaultValue) { + if (key == "" || key == null) { + return defaultValue; + } + String result = (String) map.get(key); + if (result == null) { + return defaultValue; + } else { + return result; + } + } + + public static int getIntFromMap(Map<String, Object> map, String key) { + if (key == "" || key == null) { + return 0; + } + if (map.get(key) == null) { + return 0; + } + return Integer.parseInt((String) map.get(key)); + } + + /** + * 打log接口 + * @param log 要打印的log字符串 + * @return 返回log + */ + public static String log(Object log){ + System.out.println(log.toString()); + return log.toString(); + } + + /** + * 读取本地的xml数据,一般用来自测用 + * @param localPath 本地xml文件路径 + * @return 读到的xml字符串 + */ + public static String getLocalXMLString(String localPath) throws IOException { + return Util.inputStreamToString(Util.class.getResourceAsStream(localPath)); + } + +} + diff --git a/src/main/java/cc/mrbird/febs/pay/util/WebUtil.java b/src/main/java/cc/mrbird/febs/pay/util/WebUtil.java new file mode 100644 index 0000000..a66f49a --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/WebUtil.java @@ -0,0 +1,298 @@ +package cc.mrbird.febs.pay.util; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; +import java.io.File; +import java.lang.reflect.ParameterizedType; +import java.util.Map; + +/** + * 针对ssh项目提供的一些实用性的方法。 + * + * @author JIANGYOUYAO + * @email 935090232@qq.com + * @date Dec 11, 2017 + */ +@Component +public class WebUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + WebUtil.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } + + public static <T> T getBean(String beanName, Class<T> clazz) { + return applicationContext.getBean(beanName, clazz); + } + + /** + * 获得web资源的绝对路径 + * + * @author JiangYouYao + * @date 2014年10月14日-上午8:31:01 + * @param path + * @return + */ + public static String getResourceRealPath(String path) { + return getServletContext().getRealPath(path); + } + + /** + * + * 获取web项目的访问URl + * @author:姜友瑶 + * @return 返回类型 String + * @date 2016年11月16日 + */ + public static String getWebUrl() { + return getRequest().getScheme() + "://" + getRequest().getServerName() + ":" + getRequest().getServerPort() + + getRequest().getContextPath() + "/"; + } + + /** + * 获得该类的泛型类型 + * @Return: Class 泛型的类型 + * @Author: JiangYouYao + * @Version: V1.00 (版本号1.0) + * @Create Date: 2014-8-12 (创建日期) + */ + @SuppressWarnings("rawtypes") + public static Class getClass(Class clazz) { + // 泛型转换 + ParameterizedType pt = (ParameterizedType) clazz.getGenericSuperclass(); + return (Class) pt.getActualTypeArguments()[0]; + } + + /** + * 2016/6/2 + * + * @author xieguangya + * @return getRequest + */ + public static HttpServletRequest getRequest() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + } + + /** + * + * 在当前请求的request中获取一个值 + * @author:姜友瑶 + * @return + * @date 2016年11月11日 + */ + public static Object getRequestAttribute(String name) { + return getRequest().getAttribute(name); + } + + /** + * + * 在当前请求的request中新增一个值 + * @author:姜友瑶 + * @return + * @date 2016年11月11日 + */ + public static void setRequestAttribute(String name, Object o) { + getRequest().setAttribute(name, o); + } + + /** + * + * 在request中删除一个值 + * @author:姜友瑶 + * @return + * @date 2016年11月11日 + */ + public static void removeRequestAttribute(String name) { + getRequest().removeAttribute(name); + } + + /** + * + * 在Session中新增一个值 + * @author:姜友瑶 + * @return + * @date 2016年11月11日 + */ + public static void setSessionAttribute(String name, Object o) { + getSession().setAttribute(name, o); + } + + /** + * + * 在当前session中获取一个值 + * @author:姜友瑶 + * @param <T> + * @return + * @date 2016年11月11日 + */ + public static <T> T getSessionAttribute(String name) { + return (T) getSession().getAttribute(name); + } + + /** + * + * 在Session中删除一个值 + * @author:姜友瑶 + * @return + * @date 2016年11月11日 + */ + public static void removeSessionAttribute(String name) { + getSession().removeAttribute(name); + } + + /** + * 获取session + * + * @author Matrix-J + * @return HttpSession + */ + /** + * 获取session + * + * @author Matrix-J + * @return HttpSession + */ + public static HttpSession getSession() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession(); + } + + /** + * 2016年6月15日 获取ServletContext + * + * @author Matrix-J + * @return getServletContext + */ + public static ServletContext getServletContext() { + return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getSession() + .getServletContext(); + } + + public static final String LEFT_SLASH = "/"; + /** + * 常量“字符.” + */ + public static final String CHARACTER_ALL = "\\."; + + /** + * 常量“.class” + */ + public static final String CLASS_FILE_EXTEND_NAME = ".class"; + /** + * 常量“一个空格” + */ + public static final String CHARACTER_BLANK = " "; + /** + * 空格转码后结果 + */ + public static final String SPACE_REPLEACE_STRING = "%20"; + /** + * 常量“字符左斜杠” + */ + public static final String CHARACTER_LEFT = "\\/"; + /** + * 常量"WEB-INF"路径 + */ + public static final String CONFIG_ROOT = "WEB-INF/"; + /** + * 文件协议 + */ + public static final String FILE_PROTOCOL = "file:"; + + /** + * <li>功能简述:获取项目的实际路径 + * <li>详细描述:WEB-INF + */ + public static String getContextPath() { + + String name = WebUtil.class.getName(); + name = LEFT_SLASH + name.replaceAll(CHARACTER_ALL, CHARACTER_LEFT) + CLASS_FILE_EXTEND_NAME; + String space = SPACE_REPLEACE_STRING; + String path = WebUtil.class.getResource(name).getPath(); + path = path.substring(0, path.indexOf(CONFIG_ROOT) + CONFIG_ROOT.length()); + path = path.replaceAll(space, CHARACTER_BLANK); + if (path.startsWith(FILE_PROTOCOL)) { + path = path.substring(FILE_PROTOCOL.length()); + } + return path; + } + + /** + * <li>功能简述:获得发布目录路径 + * <li>详细描述:webapps + */ + public static String getDeployPath() { + + File tempDir = new File(getContextPath()); + return tempDir.getParentFile().getParentFile().getAbsolutePath(); + } + + /** + * <li>功能简述:获得项目目录 + */ + public static String getWebPath() { + + File tempDir = new File(getContextPath()); + return tempDir.getParentFile().getAbsolutePath(); + } + + /** + * 获取当前访问路径含参数 + */ + public static String getLocation() { + Map<String, String[]> params = getRequest().getParameterMap(); + String queryString = ""; + if (params.keySet().size() > 0) { + queryString = "?"; + for (String key : params.keySet()) { + String[] values = params.get(key); + for (int i = 0; i < values.length; i++) { + String value = values[i]; + queryString += key + "=" + value + "&"; + } + } + } + return getRequest().getScheme() + "://" + getRequest().getServerName() + ":" + getRequest().getServerPort() + + getRequest().getRequestURI() + queryString; + } + + /** + * + * + * @description 获取客户端ip地址 + * @data 2015年8月6日 下午7:15:38 + * @author Administrator + * @return + */ + public static String getCustomerIp() { + HttpServletRequest request = getRequest(); + String ip = request.getHeader("x-forwarded-for"); + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } + if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + return ip; + } +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/WechatConfigure.java b/src/main/java/cc/mrbird/febs/pay/util/WechatConfigure.java new file mode 100644 index 0000000..f69cd9f --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/WechatConfigure.java @@ -0,0 +1,53 @@ +package cc.mrbird.febs.pay.util; + +public class WechatConfigure { + + public static String UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder"; + + /** + * 发送http请求类 + */ + public static String HttpsRequestClassName = "com.matrix.component.wechat.externalInterface.common.HttpsRequest"; + public static final String TRADE_TYPE_JSAPI = "JSAPI"; + + // 2)被扫支付查询API + public static String PAY_QUERY_API = "https://api.mch.weixin.qq.com/pay/orderquery"; + + + + /** + * 微信商户号 + */ + public static final String WECHARPAY_MCHID = "1605533690"; + /** + * 支付秘钥 + */ + public static final String WECHARPAY_SECRET = "CSxc168888CSxc168888CSxc168888xc"; + + /** + * 小程序APPID + */ + public static final String MINIPROGRAM_APPID = "wx5cc58f796224af61"; + // 8) 企业付款API + public static String COM_PAY_API="https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers"; + + /** + * 发送 SSL请求,企业付款,退款用 + */ + public static String HttpsRequestClassName2 = "com.matrix.component.wechat.externalInterface.common.HttpsRequest2"; + + // 3)退款API + public static String REFUND_API = "https://api.mch.weixin.qq.com/secapi/pay/refund"; + + /** + * 成功 + */ + public static final String CODE_SUCCESS = "SUCCESS"; + /** + * SUCCESS报文 + */ + public static final String RESULT_XML_SUCCESS = "<xml><return_code><![CDATA[SUCCESS]]></return_code>" + + "<return_msg><![CDATA[OK]]></return_msg></xml> "; + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/WeixinServiceUtil.java b/src/main/java/cc/mrbird/febs/pay/util/WeixinServiceUtil.java new file mode 100644 index 0000000..1125bb7 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/WeixinServiceUtil.java @@ -0,0 +1,151 @@ +package cc.mrbird.febs.pay.util; + +import cc.mrbird.febs.common.exception.FebsException; +import cc.mrbird.febs.common.properties.XcxProperties; +import cc.mrbird.febs.common.utils.SpringContextHolder; +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 lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; + +/**微信工具类 + * @author jiangyouyao + * + */ +@Slf4j +@Service(value="weixinServiceUtil") +public class WeixinServiceUtil { + + private final XcxProperties xcxProperties = SpringContextHolder.getBean(XcxProperties.class); + + /** + * 支付"175.9.82.254" + * WebUtil.getRequest().getRemoteAddr() + * getRemortIP(WebUtil.getRequest()) + * @Description 公众号支付,生成预支付订单 + @date 2017年6月27日 + @atuhor jiangyouyao + * @param desc 描述信息 + * @param outTradeNo 订单id + * @param price 订单价格,类型为整型,单位是分,不是元,等于你的实际价格*100 + * @param openId 支付者的微信openId + * @return 预支付订单返回的结果对象(该结果对象已封装),在H5页面使用该对象信息 + * @throws Exception + */ + public BrandWCPayRequestData createOrder(String desc, String outTradeNo, int price, String openId, String attach) throws Exception { + String wecharPaynotifyUrl = xcxProperties.getWecharPaynotifyUrl(); + return buildBrandWCPayRequestData(desc, outTradeNo, price, openId, attach, wecharPaynotifyUrl); + } + + private BrandWCPayRequestData buildBrandWCPayRequestData(String desc, String outTradeNo, int price, String openId, String attach, String notifyUrl) throws Exception { + // 创建微信支付预付接口 + JsApiPayBusiness jsApiPayBusiness = new JsApiPayBusiness(); + String idAddr = getIpAddr(WebUtil.getRequest()); + + String mchID = WechatConfigure.WECHARPAY_MCHID; + String paySecret = WechatConfigure.WECHARPAY_SECRET; + String appId = WechatConfigure.MINIPROGRAM_APPID; + + JsApiPayReqData jsApiPayReqData = new JsApiPayReqData( + appId, mchID, paySecret, notifyUrl, desc, + outTradeNo, price, idAddr, openId, attach); + + // 创建预付订单并返回请求结果 + JsApiPayResData result = jsApiPayBusiness.createPrapareOrder(jsApiPayReqData); + // 把预付订单的信息存放在request域中 + WebUtil.getRequest().setAttribute("msg", result.toString()); + log.info("#---返回码:return_code = {}" , result.getReturn_code()); + log.info("#---签名信息:return_msg = {}" , result.getReturn_msg()); + if (result.getReturn_code().equals("SUCCESS")) { + // 请求成功, 构建BrandWCPayRequest发起支付需要的参数 + BrandWCPayRequestData payData = new BrandWCPayRequestData(result.getPrepay_id(),appId,paySecret); + WebUtil.getRequest().setAttribute("payData", payData); + return payData; + }else{ + log.error("创建微信支付订单失败msg={}",result.getReturn_msg()); + throw new FebsException("创建微信支付订单失败,请检查程序配置"); + } + } + + /**@Description 退款,企业付款到个人 + @date 2017年5月26日 + @atuhor jiangyouyao + * @param outTradeNo 商户订单编号(原订单编号) + * @param outRefundNo 退款编号 + * @param totalFee 原订单金额(分) + * @param refundFee 退款金额(分) + * @param opUserID 操作员id,默认为商户号 + * @return + */ +// public boolean comRefund(String outTradeNo, String outRefundNo,int totalFee, +// int refundFee, String opUserID){ +// LogUtil.info("#---outTradeNo:{}#---outRefundNo:{}#---totalFee:{}#---refundFee:{}", +// outTradeNo,outRefundNo,totalFee,refundFee); +// BusParameterSettings mchID = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.WECHARPAY_MCHID, HostInterceptor.getCompanyId()); +// if(opUserID==null){ +// opUserID=mchID.getParamValue(); +// } +// RefundResData result=null; +// boolean flag=false; +// try { +// JsApiPayBusiness jsApiPayBusiness = new JsApiPayBusiness(); +// Long companyId=HostInterceptor.getCompanyId(); +// BusParameterSettings paySecret = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.WECHARPAY_SECRET, companyId); +// BusParameterSettings appId = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.MINIPROGRAM_APPID, companyId); +// BusParameterSettings certLocalPath = busParameterSettingsDao.selectCompanyParamByCode(AppConstance.WECHARPAY_CERTLOCAL_PATH, companyId); +// +// RefundReqData refundReqData=new RefundReqData(mchID.getParamValue(),appId.getParamValue(),paySecret.getParamValue(), outTradeNo, outRefundNo, totalFee, refundFee,opUserID); +// RefundService refundService=new RefundService(); +// HttpsRequest2 request2= (HttpsRequest2) refundService.getServiceRequest(); +// request2.setCertLocalPath(certLocalPath.getParamValue()); +// request2.setMchId(mchID.getParamValue()); +// +// result = jsApiPayBusiness.refundComOrder(refundService, refundReqData); +// LogUtil.info("#退款,企业付款到个人---result:{}",result); +// //如果返回余额不足时 +// if (StringUtils.equals(AppConstance.REFUND_FAIL_NOTENOUGH, result.getErr_code())) { +// LogUtil.info("#退款失败,{}!", "商户余额不足"); +// throw new GlobleException("退款失败,请联系管理员!"); +// } +// } catch (Exception e) { +// LogUtil.error("#企业付款到个人异常#退款#outTradeNo:{}#opUserID:{}", e, outTradeNo,opUserID); +// } +// +// if (result.getResult_code().equals(WechatConfigure.SUCCESS)) { +// flag=true; +// }else{ +// flag=false; +// throw new GlobleException(result.getErr_code_des()); +// } +// return flag; +// } + + /**@Description 支付获取远程设备的ip + @date 2017年6月27日 + @atuhor jiangyouyao + * @param request + * @return + */ + public String getIpAddr(HttpServletRequest request) { + String ip = request.getHeader("x-forwarded-for"); + /* if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("Proxy-Client-IP"); + } + if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getHeader("WL-Proxy-Client-IP"); + } */ + if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { + ip = request.getRemoteAddr(); + } + if(ip!=null){ + ip=ip.split(",")[0]; + } + return ip; + } + + +} diff --git a/src/main/java/cc/mrbird/febs/pay/util/XMLParser.java b/src/main/java/cc/mrbird/febs/pay/util/XMLParser.java new file mode 100644 index 0000000..224e133 --- /dev/null +++ b/src/main/java/cc/mrbird/febs/pay/util/XMLParser.java @@ -0,0 +1,84 @@ +package cc.mrbird.febs.pay.util; + +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.xml.sax.SAXException; + +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + + +/** + * User: rizenguo + * Date: 2014/11/1 + * Time: 14:06 + */ +public class XMLParser { + + /** + * 从RefunQueryResponseString里面解析出退款订单数据 + * @param refundQueryResponseString RefundQuery API返回的数据 + * @return 因为订单数据有可能是多个,所以返回一个列表 + + public static List<RefundOrderData> getRefundOrderList(String refundQueryResponseString) throws IOException, SAXException, ParserConfigurationException { + List list = new ArrayList(); + + Map<String,Object> map = XMLParser.getMapFromXML(refundQueryResponseString); + + int count = Integer.parseInt((String) map.get("refund_count")); + Util.log("count:" + count); + + if(count<1){ + return list; + } + + RefundOrderData refundOrderData; + + for(int i=0;i<count;i++){ + refundOrderData = new RefundOrderData(); + + refundOrderData.setOutRefundNo(Util.getStringFromMap(map,"out_refund_no_" + i,"")); + refundOrderData.setRefundID(Util.getStringFromMap(map,"refund_id_" + i,"")); + refundOrderData.setRefundChannel(Util.getStringFromMap(map,"refund_channel_" + i,"")); + refundOrderData.setRefundFee(Util.getIntFromMap(map,"refund_fee_" + i)); + refundOrderData.setCouponRefundFee(Util.getIntFromMap(map,"coupon_refund_fee_" + i)); + refundOrderData.setRefundStatus(Util.getStringFromMap(map,"refund_status_" + i,"")); + list.add(refundOrderData); + } + + return list; + } +*/ + public static Map<String,Object> getMapFromXML(String xmlString) throws ParserConfigurationException, IOException, SAXException { + + //这里用Dom的方式解析回包的最主要目的是防止API新增回包字段 + DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); + DocumentBuilder builder = factory.newDocumentBuilder(); + InputStream is = Util.getStringStream(xmlString); + Document document = builder.parse(is); + + //获取到document里面的全部结点 + NodeList allNodes = document.getFirstChild().getChildNodes(); + Node node; + Map<String, Object> map = new HashMap<String, Object>(); + int i=0; + while (i < allNodes.getLength()) { + node = allNodes.item(i); + if(node instanceof Element){ + map.put(node.getNodeName(),node.getTextContent()); + } + i++; + } + return map; + + } + + +} diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml index 13e6fca..ade8eee 100644 --- a/src/main/resources/application-dev.yml +++ b/src/main/resources/application-dev.yml @@ -18,7 +18,7 @@ username: ct_test password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://120.27.238.55:3306/db_amz?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 + url: jdbc:mysql://120.27.238.55:3306/db_pingtuan?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 # username: db_mall # password: mall!@#123 # driver-class-name: com.mysql.cj.jdbc.Driver @@ -62,3 +62,10 @@ # 回调地址 noticeUrl: http://120.27.238.55:8801/api/pay/aliCallBack domain: https://openapi.alipaydev.com/gateway.do + +xcx: + wechar_login_url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code + xcx_appid: wx5cc58f796224af61 + xcx_secret: cab68768a444f9e25bb3d1bc208fb546 + debug: true + wecharPaynotifyUrl: http://120.27.238.55:8801/api/xcxPay/wxpayCallback diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index a737781..c32d80a 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -18,7 +18,7 @@ username: db_mall password: mall!@#123 driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://127.0.0.1:3306/db_mall?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 + url: jdbc:mysql://127.0.0.1:3306/db_pingtuan?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 redis: # Redis数据库索引(默认为 0) @@ -58,3 +58,10 @@ # 回调地址 noticeUrl: http://120.27.238.55:8801/api/pay/aliCallBack domain: https://openapi.alipay.com/gateway.do + +xcx: + wechar_login_url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code + xcx_appid: wx5cc58f796224af61 + xcx_secret: cab68768a444f9e25bb3d1bc208fb546 + debug: false + wecharPaynotifyUrl: http://120.27.238.55:8801/api/xcxPay/wxpayCallback diff --git a/src/main/resources/application-test.yml b/src/main/resources/application-test.yml index 1177d0f..40afa92 100644 --- a/src/main/resources/application-test.yml +++ b/src/main/resources/application-test.yml @@ -18,7 +18,7 @@ username: ct_test password: 123456 driver-class-name: com.mysql.cj.jdbc.Driver - url: jdbc:mysql://120.27.238.55:3306/db_amz?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 + url: jdbc:mysql://120.27.238.55:3306/db_pingtuan?useUnicode=true&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2b8 redis: # Redis数据库索引(默认为 0) @@ -57,4 +57,13 @@ privateKey: MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDOhu+hD2kuMh5s7IQuKjexeC4DmXxrAr/bu10rNB304NaIRUNAkGPI9tep7ZRBZqa/Tjrfom8LeeBnbA1n+SgxROSREEXDA1E3/XJY+vYivehVTD2TuA2GEnEtLXUgxQJVfz/CNIOa3rCc1nj9n4/kv03Sx/yqiKnLd6h9dRvdaY9k7DwnWPu1FT5T3bpTiU+oKaUODkcfUPpMH8aQaolzKY07M0cqZFn75Z0KFAoM6p/TDoF7JKpwdzGO5xuJe8YT4xx2OcLY++d/dzSoQvvsKh8r1yE37Z5B9FxHSHe1GuR2wOQxhgXUyaj7gden/pAVspzbjZTDdQppjzNavnzdAgMBAAECggEAKAJL+c+aeLCM5F0NXkQfdenqQBhD2hc2Q8MQUYZPJ1lHNi700FUof44SSYEU73aLZxQoo5o8GOULa/2quzGxb5oBDXkxio3h9g7LUCGN/Tz8/Uk/xJYrSIXaFv5vamHACgAUwfKabC4n2LpTxg5bOd01nlfPwtmmyxvrMCK3uzSWzxDLag0jVh9DGA97D00UOkL9QpEJ26dpBuF7pf9Nt0BtfyJMFrCbJXY2F3j65VNN4f2rOG7/DTGm434Sektj9Bc31ept9MfPw9VyRbV7EMvG5be9iDqBvLbRGhQVtBjv3N/E7p3uUI5HyxM8GOjQhSwSOJQ0gQS8vNdNN90qoQKBgQDqxoTFOsPM3+LoQj1r7CjoXhooEfpikyHpK2l8mzM4+La9ajzUJzTWT8nc0k2Qha8AvBZzJ2+kSKAjtwc/VNTu0IeEn480V9zVyBFkcC294d3A1keN5ch9wP1it5fWsVh+62T9xGXlQQIpuYeQm1BXj7kltd7vE8t6fLrmnhVkpwKBgQDhMqgZoRQGmcgrVc8F//lBO7g6ku/+GfNJnve64sRi5ZifwSiNSULVqDWmdHJiVWyYXoTvt1o3bqQorawe0c+wEzknn8ZipNDnN9tybxhKqD6pzCbRv6yWmU+9X9ZhSxYJeumn3sqxyZB7rnqJQ7/vpsoNZRvp0LS85iJVJFXO2wKBgB7O3i1jgL4pwwTnbFf1LYkQkC4h7dFxrUmDwNvxIc+gE5rXjhPo8S4OWlb34eXNJSHbjLafvi64uQr2waS15RtRkfb9WTVtMjV7g4zCi74XHZpohAtC1ARshtOlc+9gZlSBX0dNtnFXDombJwb62pgi7BDexNpqppD0PTJ2HCiRAoGAREmZIdRvfyToxwNJOLeLPNXAIrrl3Xa/CGcVFe2nwZl/s4neIyHBC4rrYeNTwC/JM1cOFqbRy5dYXiFz3RCgWvMpVLOlc8oossSEXeoEQrdL8S8/4kCuNCifPnyuRGiBcTR9X/M2Ib1Oe8LH05HgxOodwPwU/8zS0akzZgATqRsCgYA5TDAX996ThMjHr+qjLh5gdIJ+85jxP0+tqVk5Vwl3niS3qJGoLIofIgHYee9U6c1wLJU+lUTaxYpuaJPwQFbdMGGGB8i3c2XczVBShCUEedelTghl7Izwh/DILmlAQCvYsC+wWMcFdU3LhYvFGXmTx9ToRBLdtd6v45+7MXcHQw== # 回调地址 noticeUrl: http://120.27.238.55:8801/api/pay/aliCallBack - domain: https://openapi.alipaydev.com/gateway.do \ No newline at end of file + domain: https://openapi.alipaydev.com/gateway.do + +xcx: + wechar_login_url: https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code +# xcx_appid: wx5cc58f796224af61 +# xcx_secret: cab68768a444f9e25bb3d1bc208fb546 + xcx_appid: wx5cc58f796224af61 + xcx_secret: 71403646f666f9b9dca308d4f357765c + debug: true + wecharPaynotifyUrl: http://120.27.238.55:8801/api/xcxPay/wxpayCallback diff --git a/src/main/resources/mapper/modules/MallMemberMapper.xml b/src/main/resources/mapper/modules/MallMemberMapper.xml index 8e99b75..94ea777 100644 --- a/src/main/resources/mapper/modules/MallMemberMapper.xml +++ b/src/main/resources/mapper/modules/MallMemberMapper.xml @@ -400,4 +400,11 @@ select * from mall_member where level=#{level} </select> + + <select id="selectMemberByOpenId" resultType="cc.mrbird.febs.mall.entity.MallMember"> + SELECT a.* + FROM mall_member a + where a.open_id = #{openId} limit 1 + </select> + </mapper> \ No newline at end of file diff --git a/src/main/resources/mapper/modules/MallOrderInfoMapper.xml b/src/main/resources/mapper/modules/MallOrderInfoMapper.xml index 660351c..5b4901c 100644 --- a/src/main/resources/mapper/modules/MallOrderInfoMapper.xml +++ b/src/main/resources/mapper/modules/MallOrderInfoMapper.xml @@ -15,9 +15,18 @@ b.sku_image, b.cnt, b.price, - b.amount + b.amount, + c.name leader_name, + c.phone leader_phone, + c.address_pic, + c.address_area, + c.province, + c.city, + c.township, + c.detail_address from mall_order_info a inner join mall_order_item b on a.id=b.order_id + inner join mall_team_leader c on a.take_unique_code=c.unique_code <where> a.del_flag=2 <if test="record.status == 4 and record.status != 0"> @@ -35,6 +44,12 @@ <if test="record.orderType != null"> and a.order_type=#{record.orderType} </if> + <if test="record.deliveryType != null"> + and a.delivery_type=#{record.deliveryType} + </if> + <if test="record.takeUniqueCode != null"> + and a.take_unique_code=#{record.takeUniqueCode} + </if> </where> order by a.created_time desc </select> @@ -50,6 +65,7 @@ b.phone memberPhone from mall_order_info a left join mall_member b on a.member_id = b.id + left join mall_team_leader c on a.take_unique_code = c.unique_code <where> a.del_flag=2 <if test="record != null"> @@ -62,11 +78,17 @@ <if test="record.status != null and record.status != ''"> and a.status = #{record.status} </if> + <if test="record.deliveryType != null and record.deliveryType != ''"> + and a.delivery_type = #{record.deliveryType} + </if> <if test="record.orderNo != null and record.orderNo != ''"> and a.order_no like CONCAT('%', CONCAT(#{record.orderNo}, '%')) </if> <if test="record.name != null and record.name != ''"> and b.name like CONCAT('%', CONCAT(#{record.name}, '%')) + </if> + <if test="record.uniqueCode != null and record.uniqueCode != ''"> + and a.take_unique_code = #{record.uniqueCode} </if> </if> </where> @@ -99,7 +121,17 @@ <result column="comment_state" property="commentState" /> <result column="carriage" property="carriage" /> <result column="remark" property="remark" /> + <result column="take_code" property="takeCode" /> + <result column="take_unique_code" property="takeUniqueCode" /> <result column="del_flag" property="delFlag" /> + <result column="leader_name" property="leaderName" /> + <result column="leader_phone" property="leaderPhone" /> + <result column="address_pic" property="addressPic" /> + <result column="address_area" property="addressArea" /> + <result column="province" property="province" /> + <result column="city" property="city" /> + <result column="township" property="township" /> + <result column="detail_address" property="detailAddress" /> <collection property="items" ofType="cc.mrbird.febs.mall.entity.MallOrderItem"> <id property="id" column="item_id" /> <result property="orderId" column="order_id" /> @@ -129,9 +161,18 @@ b.sku_image, b.cnt, b.price, - b.amount + b.amount, + c.name leader_name, + c.phone leader_phone, + c.address_pic, + c.address_area, + c.province, + c.city, + c.township, + c.detail_address from mall_order_info a inner join mall_order_item b on a.id=b.order_id + inner join mall_team_leader c on a.take_unique_code=c.unique_code <where> a.del_flag=2 <if test="record.query != null and record.query != ''"> @@ -170,9 +211,18 @@ b.cnt, b.price, b.amount, - b.is_normal + b.is_normal, + c.name leader_name, + c.phone leader_phone, + c.address_pic, + c.address_area, + c.province, + c.city, + c.township, + c.detail_address from mall_order_info a inner join mall_order_item b on a.id=b.order_id + inner join mall_team_leader c on a.take_unique_code=c.unique_code where a.id=#{id} </select> diff --git a/src/main/resources/mapper/modules/MallTeamLeaderMapper.xml b/src/main/resources/mapper/modules/MallTeamLeaderMapper.xml new file mode 100644 index 0000000..b80a2d7 --- /dev/null +++ b/src/main/resources/mapper/modules/MallTeamLeaderMapper.xml @@ -0,0 +1,169 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> +<mapper namespace="cc.mrbird.febs.mall.mapper.MallTeamLeaderMapper"> + + <select id="selectLeaderListInPage" resultType="cc.mrbird.febs.mall.vo.AdminMallTeamLeaderVo"> + select + a.* + from mall_team_leader a + <where> + <if test="record != null"> + <if test="record.name != null and record.name != ''"> + and a.name like CONCAT('%', CONCAT(#{record.name}, '%')) + </if> + <if test="record.state != null and record.state != ''"> + and a.state = #{record.state} + </if> + </if> + </where> + order by a.created_time desc + </select> + + <select id="selectApiLeaderListInPage" resultType="cc.mrbird.febs.mall.entity.MallTeamLeader"> + select + a.*, + ROUND( + 6378.138 * 2 * ASIN( + SQRT( + POW(SIN((#{record.latitude} * PI() / 180 - a.latitude * PI() / 180) / 2),2) + + COS(40.0497810000 * PI() / 180) * COS(a.latitude * PI() / 180) + * POW(SIN((#{record.longitude} * PI() / 180 - a.longitude * PI() / 180) / 2),2) + ) + ) * 1000 + ) AS distance + from mall_team_leader a + <where> + a.state = 1 + <if test="record.query != null and record.query != ''"> + and (a.name like CONCAT('%', CONCAT(#{record.query}, '%')) + or a.phone like CONCAT('%', CONCAT(#{record.query}, '%')) + or a.address_area like CONCAT('%', CONCAT(#{record.query}, '%'))) + </if> + </where> + order by distance ASC + </select> + + <select id="selectListByMemberIdAndState" resultType="cc.mrbird.febs.mall.entity.MallTeamLeader"> + select + a.* + from mall_team_leader a + where a.state = #{state} and a.member_id = #{memberId} + </select> + + + <resultMap id="OrderInfoMap" type="cc.mrbird.febs.mall.entity.MallOrderInfo"> + <id column="id" property="id" /> + <result column="order_no" property="orderNo" /> + <result column="member_id" property="memberId" /> + <result column="order_time" property="orderTime" /> + <result column="pay_time" property="payTime" /> + <result column="amount" property="amount" /> + <result column="pay_method" property="payMethod" /> + <result column="pay_order_no" property="payOrderNo" /> + <result column="pay_result" property="payResult" /> + <result column="status" property="status" /> + <result column="cancel_type" property="cancelType" /> + <result column="name" property="name" /> + <result column="phone" property="phone" /> + <result column="address" property="address" /> + <result column="longitude" property="longitude" /> + <result column="latitude" property="latitude" /> + <result column="order_type" property="orderType" /> + <result column="comment_state" property="commentState" /> + <result column="carriage" property="carriage" /> + <result column="remark" property="remark" /> + <result column="del_flag" property="delFlag" /> + <collection property="items" ofType="cc.mrbird.febs.mall.entity.MallOrderItem"> + <id property="id" column="item_id" /> + <result property="orderId" column="order_id" /> + <result property="goodsId" column="goods_id" /> + <result property="skuId" column="sku_id" /> + <result property="goodsName" column="goods_name" /> + <result property="styleName" column="style_name" /> + <result property="skuName" column="sku_name" /> + <result property="skuImage" column="sku_image" /> + <result property="cnt" column="cnt" /> + <result property="price" column="price" /> + <result property="amount" column="amount" /> + <result property="isNormal" column="is_normal" /> + </collection> + </resultMap> + + <select id="selectApiLeaderOrderListInPage" resultMap="OrderInfoMap"> + select + a.*, + b.id item_id, + b.order_id, + b.goods_id, + b.sku_id, + b.goods_name, + b.style_name, + b.sku_name, + b.sku_image, + b.cnt, + b.price, + b.amount + from mall_order_info a + inner join mall_order_item b on a.id=b.order_id + inner join mall_member c on a.take_unique_code=c.invite_id + <where> + a.del_flag=2 + and a.delivery_type = 1 + and c.id=#{record.memberId} + <if test="record.query != null and record.query != ''"> + and ( a.name like CONCAT('%', CONCAT(#{record.query}, '%')) + or a.phone like CONCAT('%', CONCAT(#{record.query}, '%')) + or a.take_code like CONCAT('%', CONCAT(#{record.query}, '%')) + ) + </if> + <if test="record.status == 4 and record.status != 0"> + and a.status = 4 + </if> + <if test="record.status != 4 and record.status != 1 and record.status != 0 and record.status != 5"> + and a.status = #{record.status} + </if> + <if test="record.status == 5"> + and a.status = 7 + </if> + <if test="record.status == 1"> + and a.status = 2 + </if> + <if test="record.orderType != null"> + and a.order_type=#{record.orderType} + </if> + </where> + order by a.created_time desc + </select> + + <select id="getMallTeamLeaderList" resultType="cc.mrbird.febs.mall.entity.MallTeamLeader"> + select + a.* + from mall_team_leader a + where a.state = 1 + </select> + + <select id="selectLeaderByUniqueCode" resultType="cc.mrbird.febs.mall.entity.MallTeamLeader"> + select + a.* + from mall_team_leader a + where a.unique_code = #{uniqueCode} limit 1 + </select> + + <select id="selectLeaderByLonAndLat" resultType="cc.mrbird.febs.mall.entity.MallTeamLeader"> + select + a.*, + ROUND( + 6378.138 * 2 * ASIN( + SQRT( + POW(SIN((#{latitude} * PI() / 180 - a.latitude * PI() / 180) / 2),2) + + COS(40.0497810000 * PI() / 180) * COS(a.latitude * PI() / 180) + * POW(SIN((#{longitude} * PI() / 180 - a.longitude * PI() / 180) / 2),2) + ) + ) * 1000 + ) AS distance + from mall_team_leader a + where a.state = 1 + order by distance ASC limit 1 + </select> + +</mapper> \ No newline at end of file diff --git a/src/main/resources/templates/febs/views/modules/leader/leaderList.html b/src/main/resources/templates/febs/views/modules/leader/leaderList.html new file mode 100644 index 0000000..74430e9 --- /dev/null +++ b/src/main/resources/templates/febs/views/modules/leader/leaderList.html @@ -0,0 +1,185 @@ +<div class="layui-fluid layui-anim febs-anim" id="febs-leader" lay-title="团长列表"> + <div class="layui-row febs-container"> + <div class="layui-col-md12"> + <div class="layui-card"> + <div class="layui-card-body febs-table-full"> + <form class="layui-form layui-table-form" lay-filter="user-table-form"> + <div class="layui-row"> + <div class="layui-col-md10"> + <div class="layui-form-item"> + <div class="layui-inline"> + <div class="layui-input-inline"> + <input type="text" placeholder="名称" name="name" autocomplete="off" class="layui-input"> + </div> + </div> + <div class="layui-inline"> + <label class="layui-form-label layui-form-label-sm">审核状态</label> + <div class="layui-input-inline"> + <select name="state"> + <option value="">请选择</option> + <option value="1">通过</option> + <option value="2">不通过</option> + <option value="3">申请中</option> + </select> + </div> + </div> + </div> + </div> + <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area"> + <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain table-action" id="query"> + <i class="layui-icon"></i> + </div> + <div class="layui-btn layui-btn-sm layui-btn-primary febs-button-green-plain table-action" id="reset"> + <i class="layui-icon"></i> + </div> + </div> + </div> + </form> + <table lay-filter="leaderTable" lay-data="{id: 'leaderTable'}"></table> + <style type="text/css"> + .layui-table-cell{ + text-align:center; + height: auto; + white-space: nowrap; /*文本不会换行,在同一行显示*/ + overflow: hidden; /*超出隐藏*/ + text-overflow: ellipsis; /*省略号显示*/ + } + .layui-table img{ + max-width:100px + } + </style> + </div> + </div> + </div> + </div> +</div> +<!-- 表格操作栏 start --> +<script type="text/html" id="user-option"> + <span shiro:lacksPermission="user:view,user:update,user:delete"> + <span class="layui-badge-dot febs-bg-orange"></span> 无权限 + </span> + <a lay-event="edit" shiro:hasPermission="user:update"><i + class="layui-icon febs-edit-area febs-blue"></i></a> +</script> +<!-- 表格操作栏 end --> +<script data-th-inline="none" type="text/javascript"> + // 引入组件并初始化 + layui.use([ 'jquery', 'form', 'table', 'febs'], function () { + var $ = layui.jquery, + febs = layui.febs, + form = layui.form, + table = layui.table, + $view = $('#febs-leader'), + $query = $view.find('#query'), + $reset = $view.find('#reset'), + $searchForm = $view.find('form'), + sortObject = {field: 'phone', type: null}, + tableIns; + + form.render(); + + // 表格初始化 + initTable(); + + // 初始化表格操作栏各个按钮功能 + table.on('tool(leaderTable)', function (obj) { + var data = obj.data, + layEvent = obj.event; + if (layEvent === 'leaderUpdate') { + febs.modal.open('编辑', 'modules/leader/leaderUpdate/' + data.id, { + btn: ['提交', '取消'], + area:['100%','100%'], + yes: function (index, layero) { + $('#febs-leader-update').find('#submit').trigger('click'); + }, + btn2: function () { + layer.closeAll(); + } + }); + } + if (layEvent === 'seeImgThumb') { + var t = $view.find('#seeImgThumb'+data.id+''); + //页面层 + layer.open({ + type: 1, + title: "图片", + skin: 'layui-layer-rim', //加上边框 + area: ['80%', '80%'], //宽高 + shadeClose: true, //开启遮罩关闭 + end: function (index, layero) { + return false; + }, + content: '<div style="text-align:center"><img src="' + $(t).attr('src') + '" /></div>' + }); + } + }); + + // 查询按钮 + $query.on('click', function () { + var params = $.extend(getQueryParams(), {field: sortObject.field, order: sortObject.type}); + tableIns.reload({where: params, page: {curr: 1}}); + }); + + // 刷新按钮 + $reset.on('click', function () { + $searchForm[0].reset(); + sortObject.type = 'null'; + tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject}); + }); + + + function initTable() { + tableIns = febs.table.init({ + elem: $view.find('table'), + id: 'leaderTable', + url: ctx + 'admin/leader/leaderList', + cols: [[ + {field: 'name', title: '姓名', minWidth: 150,align:'left'}, + {field: 'phone', title: '电话', minWidth: 150,align:'left'}, + {field: 'addressPic', title: '自提点照片', + templet: function (d) { + return '<a lay-event="seeImgThumb"><img id="seeImgThumb'+d.id+'" src="'+d.addressPic+'" alt=""></a>'; + }, minWidth: 150,align:'center'}, + {field: 'state', title: '状态', + templet: function (d) { + if (d.state === 1) { + return '<span style="color:green;">通过</span>' + } else if (d.state === 2) { + return '<span style="color:red;">拒绝</span>' + }else if (d.state === 3) { + return '<span style="color:blue;">待审核</span>' + }else{ + return '' + } + }, minWidth: 80,align:'center'}, + {title: '操作', + templet: function (d) { + if (d.state === 3) { + return '' + + '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="leaderUpdate" shiro:hasPermission="user:update">审核</button>' + }else{ + return ''; + } + },minWidth: 160,align:'center'} + ]] + }); + } + + form.on('switch(startOrCloseSwitch)', function (data) { + if (data.elem.checked) { + startAct(data.value); + } else { + closeAct(data.value); + } + }) + + // 获取查询参数 + function getQueryParams() { + return { + name: $searchForm.find('input[name="name"]').val().trim(), + state: $searchForm.find("select[name='state']").val(), + }; + } + + }) +</script> \ No newline at end of file diff --git a/src/main/resources/templates/febs/views/modules/leader/leaderUpdate.html b/src/main/resources/templates/febs/views/modules/leader/leaderUpdate.html new file mode 100644 index 0000000..3286716 --- /dev/null +++ b/src/main/resources/templates/febs/views/modules/leader/leaderUpdate.html @@ -0,0 +1,143 @@ +<style> + #febs-leader-update { + padding: 20px 25px 25px 0; + } + + #febs-leader-update .layui-treeSelect .ztree li a, .ztree li span { + margin: 0 0 2px 3px !important; + } + #febs-leader-update #data-permission-tree-block { + border: 1px solid #eee; + border-radius: 2px; + padding: 3px 0; + } + #febs-leader-update .layui-treeSelect .ztree li span.button.switch { + top: 1px; + left: 3px; + } + #febs-leader-update img{ + max-width:200px + } + +</style> +<div class="layui-fluid" id="febs-leader-update"> + <form class="layui-form" action="" lay-filter="febs-leader-update-form"> + <div class="layui-form-item febs-hide"> + <label class="layui-form-label">id:</label> + <div class="layui-input-block"> + <input type="text" name="id"> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">姓名:</label> + <div class="layui-input-block"> + <input type="text" name="name" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">手机号码:</label> + <div class="layui-input-block"> + <input type="text" name="phone" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">省:</label> + <div class="layui-input-block"> + <input type="text" name="province" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">市:</label> + <div class="layui-input-block"> + <input type="text" name="city" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">区:</label> + <div class="layui-input-block"> + <input type="text" name="township" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">详细地址:</label> + <div class="layui-input-block"> + <input type="text" name="detailAddress" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">自提点名称:</label> + <div class="layui-input-block"> + <input type="text" name="addressArea" class="layui-input" readonly> + <div class="layui-form-mid layui-word-aux">小区名称(自提点名称)</div> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">自提点照片:</label> + <div class="layui-input-block"> + <img alt="头像" data-th-src="${leaderInfo.addressPic}" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">经度:</label> + <div class="layui-input-block"> + <input type="text" name="longitude" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">纬度:</label> + <div class="layui-input-block"> + <input type="text" name="latitude" class="layui-input" readonly> + </div> + </div> + <div class="layui-form-item"> + <label class="layui-form-label febs-form-item-require">审核结果:</label> + <div class="layui-input-block"> + <input type="radio" name="isOk" value="1" title="同意" checked=""> + <input type="radio" name="isOk" value="2" title="拒绝"> + </div> + </div> + <div class="layui-form-item febs-hide"> + <button class="layui-btn" lay-submit="" lay-filter="febs-leader-update-submit" id="submit"></button> + </div> + </form> +</div> + +<script data-th-inline="javascript"> + layui.use(['febs', 'form', 'formSelects', 'treeSelect', 'eleTree'], function () { + var $ = layui.$, + febs = layui.febs, + layer = layui.layer, + form = layui.form, + leaderInfo = [[${leaderInfo}]], + $view = $('#febs-leader-update'), + _deptTree; + form.render(); + + initUserValue(); + + function initUserValue() { + form.val("febs-leader-update-form", { + "id": leaderInfo.id, + "name": leaderInfo.name, + "phone": leaderInfo.phone, + "addressPic": leaderInfo.addressPic, + "province": leaderInfo.province, + "city": leaderInfo.city, + "township": leaderInfo.township, + "addressArea": leaderInfo.addressArea, + "detailAddress": leaderInfo.detailAddress, + "longitude": leaderInfo.longitude, + "latitude": leaderInfo.latitude + }); + } + + form.on('submit(febs-leader-update-submit)', function (data) { + febs.post(ctx + 'admin/leader/leaderUpdate', data.field, function () { + layer.closeAll(); + febs.alert.success('操作成功'); + $('#febs-leader').find('#reset').click(); + }); + return false; + }); + }); +</script> \ No newline at end of file diff --git a/src/main/resources/templates/febs/views/modules/order/orderList.html b/src/main/resources/templates/febs/views/modules/order/orderList.html index 8ea89e4..b7ad4c9 100644 --- a/src/main/resources/templates/febs/views/modules/order/orderList.html +++ b/src/main/resources/templates/febs/views/modules/order/orderList.html @@ -32,6 +32,24 @@ </div> </div> <div class="layui-inline"> + <label class="layui-form-label">团长:</label> + <div class="layui-input-inline"> + <select name="uniqueCode" class="order-takeUniqueCode"> + <option value="">请选择</option> + </select> + </div> + </div> + <div class="layui-inline"> + <label class="layui-form-label layui-form-label-sm">配送方式</label> + <div class="layui-input-inline"> + <select name="deliveryType"> + <option value="">请选择</option> + <option value="1">自提</option> + <option value="2">快递</option> + </select> + </div> + </div> + <div class="layui-inline"> <label class="layui-form-label layui-form-label-sm">支付状态</label> <div class="layui-input-inline"> <select name="payResult"> @@ -81,14 +99,15 @@ </script> <script type="text/html" id="tableToolBar"> <div class="layui-btn-container"> - <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain" lay-event="exportDeliver">导出未发货订单</button> + <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain" lay-event="exportDeliverOne">导出未发货订单(自提)</button> + <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain" lay-event="exportDeliverTwo">导出未发货订单(快递)</button> <button class="layui-btn layui-btn-sm layui-btn-primary febs-button-blue-plain" id="importDeliver" lay-event="importDeliver">导入发货</button> </div> </script> <!-- 表格操作栏 end --> <script data-th-inline="none" type="text/javascript"> // 引入组件并初始化 - layui.use([ 'jquery', 'form', 'table', 'febs', 'upload'], function () { + layui.use([ 'jquery', 'form', 'table', 'febs', 'formSelects', 'upload'], function () { var $ = layui.jquery, febs = layui.febs, form = layui.form, @@ -100,18 +119,40 @@ $searchForm = $view.find('form'), $add = $view.find('#add'), sortObject = {field: 'phone', type: null}, + formSelects = layui.formSelects, tableIns; form.render(); + + formSelects.render(); + //(下拉框) + $.get(ctx + 'admin/leader/selectList', function (data) { + for (var k in data) + { + $(".order-takeUniqueCode").append("<option value='" + data[k].uniqueCode + "'>" + data[k].name + "</option>"); + } + layui.use('form', function () { + var form = layui.form; + form.render(); + }); + }); // 表格初始化 initTable(); table.on('toolbar(orderTable)', function(obj){ var event = obj.event; + if (event == 'exportDeliverOne') { + let uniqueCodeValue = $searchForm.find("select[name='uniqueCode']").val(); + if(uniqueCodeValue == '' || uniqueCodeValue == null){ + febs.alert.warn('请选择团长'); + return; + } + window.location.href = ctx + "admin/order/exportOrderListOne?orderType=1&status=2&deliveryType=1&takeUniqueCode="+uniqueCodeValue; + } - if (event == 'exportDeliver') { - window.location.href = ctx + "admin/order/exportOrderList?orderType=1&status=2"; + if (event == 'exportDeliverTwo') { + window.location.href = ctx + "admin/order/exportOrderList?orderType=1&status=2&deliveryType=2"; } }); @@ -205,6 +246,16 @@ {field: 'amount', title: '订单金额', minWidth: 120,align:'left'}, {field: 'carriage', title: '运费', minWidth: 120,align:'left'}, {field: 'orderTime', title: '下单时间', minWidth: 200,align:'left'}, + {field: 'deliveryType', title: '配送方式', + templet: function (d) { + if (d.deliveryType === 1) { + return '<span style="color:dodgerblue;">自提</span>' + } else if (d.deliveryType === 2) { + return '<span style="color:forestgreen;">快递</span>' + }else{ + return '' + } + }, minWidth: 120,align:'center'}, {field: 'status', title: '状态', templet: function (d) { if (d.status === 1) { @@ -230,7 +281,7 @@ {field: 'payOrderNo', title: '支付订单号', minWidth: 200,align:'left'}, {title: '操作', templet: function (d) { - if (d.status === 2) { + if (d.status === 2 && d.deliveryType === 2) { return '<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="deliverGoods" shiro:hasPermission="user:update">发货</button>' +'<button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="seeOrder" shiro:hasPermission="user:update">详情</button>' }else{ @@ -249,6 +300,8 @@ orderNo: $searchForm.find('input[name="orderNo"]').val().trim(), payResult: $searchForm.find("select[name='payResult']").val(), status: $searchForm.find("select[name='status']").val(), + deliveryType: $searchForm.find("select[name='deliveryType']").val(), + uniqueCode: $searchForm.find("select[name='uniqueCode']").val(), }; } -- Gitblit v1.9.1