修复支付 导出最新sql

This commit is contained in:
hupeng
2023-10-11 11:39:10 +08:00
parent 85b0868dde
commit 441dad9ef6
30 changed files with 838 additions and 122 deletions

View File

@ -11,7 +11,7 @@ SERVER_NAME=yshop-server
# 环境 # 环境
PROFILES_ACTIVE=development PROFILES_ACTIVE=development
# 健康检查 URL # 健康检查 URL
HEALTH_CHECK_URL=http://127.0.0.1:48080/actuator/health/ HEALTH_CHECK_URL=http://127.0.0.1:48082/actuator/health/
# heapError 存放路径 # heapError 存放路径
HEAP_ERROR_PATH=$BASE_PATH/heapError HEAP_ERROR_PATH=$BASE_PATH/heapError

View File

@ -1,10 +1,10 @@
{ {
"local": { "local": {
"baseUrl": "http://127.0.0.1:48080/admin-api", "baseUrl": "http://127.0.0.1:48082/admin-api",
"token": "test1", "token": "test1",
"adminTenentId": "1", "adminTenentId": "1",
"appApi": "http://127.0.0.1:48080/app-api", "appApi": "http://127.0.0.1:48082/app-api",
"appToken": "test247", "appToken": "test247",
"appTenentId": "1" "appTenentId": "1"
}, },

File diff suppressed because one or more lines are too long

View File

@ -13,7 +13,7 @@ public class FtpFileClientTest {
public void test() { public void test() {
// 创建客户端 // 创建客户端
FtpFileClientConfig config = new FtpFileClientConfig(); FtpFileClientConfig config = new FtpFileClientConfig();
config.setDomain("http://127.0.0.1:48080"); config.setDomain("http://127.0.0.1:48082");
config.setBasePath("/home/ftp"); config.setBasePath("/home/ftp");
config.setHost("kanchai.club"); config.setHost("kanchai.club");
config.setPort(221); config.setPort(221);

View File

@ -12,7 +12,7 @@ public class LocalFileClientTest {
public void test() { public void test() {
// 创建客户端 // 创建客户端
LocalFileClientConfig config = new LocalFileClientConfig(); LocalFileClientConfig config = new LocalFileClientConfig();
config.setDomain("http://127.0.0.1:48080"); config.setDomain("http://127.0.0.1:48082");
config.setBasePath("/Users/yshop/file_test"); config.setBasePath("/Users/yshop/file_test");
LocalFileClient client = new LocalFileClient(0L, config); LocalFileClient client = new LocalFileClient(0L, config);
client.init(); client.init();

View File

@ -12,7 +12,7 @@ public class SftpFileClientTest {
public void test() { public void test() {
// 创建客户端 // 创建客户端
SftpFileClientConfig config = new SftpFileClientConfig(); SftpFileClientConfig config = new SftpFileClientConfig();
config.setDomain("http://127.0.0.1:48080"); config.setDomain("http://127.0.0.1:48082");
config.setBasePath("/home/ftp"); config.setBasePath("/home/ftp");
config.setHost("kanchai.club"); config.setHost("kanchai.club");
config.setPort(222); config.setPort(222);

View File

@ -0,0 +1,44 @@
package co.yixiang.yshop.module.infra.controller.app.file;
import cn.hutool.core.io.IoUtil;
import co.yixiang.yshop.framework.common.pojo.CommonResult;
import co.yixiang.yshop.framework.operatelog.core.annotations.OperateLog;
import co.yixiang.yshop.module.infra.controller.app.file.vo.file.FileUploadReqVO;
import co.yixiang.yshop.module.infra.service.file.FileService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import static co.yixiang.yshop.framework.common.pojo.CommonResult.success;
@Tag(name = "用户 APP - 文件存储")
@RestController
@RequestMapping("/infra/file")
@Validated
@Slf4j
public class AppFileController {
@Resource
private FileService fileService;
@PostMapping("/upload")
@Operation(summary = "上传文件")
@OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要
public CommonResult<String> uploadFile(FileUploadReqVO uploadReqVO) throws Exception {
MultipartFile file = uploadReqVO.getFile();
String path = uploadReqVO.getPath();
return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream())));
}
}

View File

@ -0,0 +1,20 @@
package co.yixiang.yshop.module.infra.controller.app.file.vo.file;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotNull;
@Schema(description = "app - 上传文件 Request VO")
@Data
public class FileUploadReqVO {
@Schema(description = "文件附件", required = true)
@NotNull(message = "文件附件不能为空")
private MultipartFile file;
@Schema(description = "文件附件", example = "yshopyuanma.png")
private String path;
}

View File

@ -29,7 +29,7 @@
</dependency> </dependency>
<dependency> <dependency>
<groupId>co.yixiang.boot</groupId> <groupId>co.yixiang.boot</groupId>
<artifactId>yshop-module-pay-api</artifactId> <artifactId>yshop-module-pay-biz</artifactId>
<version>${revision}</version> <version>${revision}</version>
</dependency> </dependency>
<dependency> <dependency>

View File

@ -15,6 +15,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List; import java.util.List;
import static co.yixiang.yshop.framework.common.pojo.CommonResult.success; import static co.yixiang.yshop.framework.common.pojo.CommonResult.success;
@ -35,7 +36,7 @@ public class AppOrderAfterSalesController {
@PreAuthenticated @PreAuthenticated
@PostMapping("/applyForAfterSales") @PostMapping("/applyForAfterSales")
@Operation(summary = "申请售后") @Operation(summary = "申请售后")
public CommonResult<Boolean> applyForAfterSales(@RequestBody AppStoreAfterSalesParam storeAfterSalesParam) { public CommonResult<Boolean> applyForAfterSales(@Valid @RequestBody AppStoreAfterSalesParam storeAfterSalesParam) {
Long uid = getLoginUserId(); Long uid = getLoginUserId();
appStoreAfterSalesService.applyForAfterSales(uid, storeAfterSalesParam); appStoreAfterSalesService.applyForAfterSales(uid, storeAfterSalesParam);
return success(true); return success(true);
@ -100,13 +101,7 @@ public class AppOrderAfterSalesController {
Boolean revoke = appStoreAfterSalesService.revoke(key, uid, id); Boolean revoke = appStoreAfterSalesService.revoke(key, uid, id);
return success(revoke); return success(revoke);
} }
//
// @PreAuthenticated
// @GetMapping(value = "/yxExpress")
// @Operation(summary = "查询快递")
// public ApiResult<List<YxExpress>> getYxExpresss(YxExpressQueryCriteria criteria) {
// return ApiResult.ok(yxExpressService.queryAll(criteria));
// }
@PreAuthenticated @PreAuthenticated

View File

@ -3,6 +3,7 @@ package co.yixiang.yshop.module.order.controller.app.afterorder.param;
import lombok.Data; import lombok.Data;
import javax.validation.constraints.NotBlank; import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import java.util.List; import java.util.List;
/** /**
@ -20,7 +21,7 @@ public class AppStoreAfterSalesParam {
/** /**
* 服务类型 0仅退款1退货退款 * 服务类型 0仅退款1退货退款
*/ */
@NotBlank //@NotBlank
private Integer serviceType; private Integer serviceType;
/** /**
@ -42,7 +43,7 @@ public class AppStoreAfterSalesParam {
/** /**
* 商品数据 * 商品数据
*/ */
@NotBlank //@NotNull
private List<AppProsuctParam> productParamList; private List<AppProsuctParam> productParamList;
} }

View File

@ -90,6 +90,7 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
StoreOrderDO yxStoreOrder = storeOrderMapper.selectOne(Wrappers.<StoreOrderDO>lambdaQuery() StoreOrderDO yxStoreOrder = storeOrderMapper.selectOne(Wrappers.<StoreOrderDO>lambdaQuery()
.eq(StoreOrderDO::getOrderId, storeAfterSalesParam.getOrderCode()) .eq(StoreOrderDO::getOrderId, storeAfterSalesParam.getOrderCode())
.eq(StoreOrderDO::getUid, userId)); .eq(StoreOrderDO::getUid, userId));
System.out.println("storeAfterSalesParam:"+storeAfterSalesParam);
afterOrderRedisDAO.set(userId,storeAfterSalesParam.getOrderCode(),yxStoreOrder.getStatus().toString()); afterOrderRedisDAO.set(userId,storeAfterSalesParam.getOrderCode(),yxStoreOrder.getStatus().toString());
checkOrder(yxStoreOrder); checkOrder(yxStoreOrder);
//商品除去优惠后的总价格 //商品除去优惠后的总价格
@ -162,10 +163,15 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
*/ */
@Override @Override
public List<AppStoreOrderCartInfoVo> checkOrderDetails(String key) { public List<AppStoreOrderCartInfoVo> checkOrderDetails(String key) {
List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper.selectList(Wrappers.<StoreOrderCartInfoDO>lambdaQuery().eq(StoreOrderCartInfoDO::getOid, key)); List<StoreOrderCartInfoDO> yxStoreOrderCartInfos = storeOrderCartInfoMapper
StoreOrderDO yxStoreOrder = storeOrderMapper.selectById(key); .selectList(Wrappers.<StoreOrderCartInfoDO>lambdaQuery().eq(StoreOrderCartInfoDO::getOrderId, key));
if(yxStoreOrderCartInfos == null || yxStoreOrderCartInfos.isEmpty()){
throw exception(STORE_ORDER_NOT_EXISTS);
}
StoreOrderDO yxStoreOrder = storeOrderMapper.selectById(yxStoreOrderCartInfos.get(0).getId());
//查询 售后信息 //查询 售后信息
StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery().eq(StoreAfterSalesDO::getOrderCode, yxStoreOrder.getOrderId())); StoreAfterSalesDO storeAfterSales = this.baseMapper.selectOne(Wrappers.<StoreAfterSalesDO>lambdaQuery()
.eq(StoreAfterSalesDO::getOrderCode, yxStoreOrder.getOrderId()));
List<AppStoreOrderCartInfoVo> yxStoreOrderCartInfoVos = new ArrayList<>(); List<AppStoreOrderCartInfoVo> yxStoreOrderCartInfoVos = new ArrayList<>();
for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) { for (StoreOrderCartInfoDO yxStoreOrderCartInfo : yxStoreOrderCartInfos) {
@ -182,11 +188,14 @@ public class AppStoreAfterSalesServiceImpl extends ServiceImpl<StoreAfterSalesMa
//商品优惠前总金额 //商品优惠前总金额
BigDecimal totalAmountOfGoods = NumberUtil.mul(cartInfo.getTruePrice(), cartInfo.getCartNum()); BigDecimal totalAmountOfGoods = NumberUtil.mul(cartInfo.getTruePrice(), cartInfo.getCartNum());
//商品优惠总金额 //商品优惠总金额
BigDecimal commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods, NumberUtil.sub(yxStoreOrder.getTotalPrice(), yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice()); // BigDecimal commodityDiscountAmount = BigDecimal.ZERO;
// if()
BigDecimal commodityDiscountAmount = NumberUtil.mul(NumberUtil.div(totalAmountOfGoods,
NumberUtil.sub(yxStoreOrder.getTotalPrice(), yxStoreOrder.getPayPostage())), yxStoreOrder.getCouponPrice());
yxStoreOrderCartInfoVo.setRefundablePrice(NumberUtil.sub(totalAmountOfGoods, commodityDiscountAmount)); yxStoreOrderCartInfoVo.setRefundablePrice(NumberUtil.sub(totalAmountOfGoods, commodityDiscountAmount));
yxStoreOrderCartInfoVo.setReasons(storeAfterSales.getReasons()); //yxStoreOrderCartInfoVo.setReasons(storeAfterSales.getReasons());
yxStoreOrderCartInfoVos.add(yxStoreOrderCartInfoVo); yxStoreOrderCartInfoVos.add(yxStoreOrderCartInfoVo);
} }

View File

@ -34,7 +34,9 @@ import co.yixiang.yshop.module.order.enums.*;
import co.yixiang.yshop.module.order.service.storeorder.dto.*; import co.yixiang.yshop.module.order.service.storeorder.dto.*;
import co.yixiang.yshop.module.order.service.storeordercartinfo.StoreOrderCartInfoService; import co.yixiang.yshop.module.order.service.storeordercartinfo.StoreOrderCartInfoService;
import co.yixiang.yshop.module.order.service.storeorderstatus.StoreOrderStatusService; import co.yixiang.yshop.module.order.service.storeorderstatus.StoreOrderStatusService;
import co.yixiang.yshop.module.pay.dal.dataobject.merchantdetails.MerchantDetailsDO;
import co.yixiang.yshop.module.pay.mq.producer.PayNoticeProducer; import co.yixiang.yshop.module.pay.mq.producer.PayNoticeProducer;
import co.yixiang.yshop.module.pay.service.merchantdetails.MerchantDetailsService;
import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo; import co.yixiang.yshop.module.product.controller.app.cart.vo.AppStoreCartQueryVo;
import co.yixiang.yshop.module.product.controller.app.product.vo.AppStoreProductRespVo; import co.yixiang.yshop.module.product.controller.app.product.vo.AppStoreProductRespVo;
import co.yixiang.yshop.module.product.dal.dataobject.shippingtemplates.ShippingTemplatesDO; import co.yixiang.yshop.module.product.dal.dataobject.shippingtemplates.ShippingTemplatesDO;
@ -70,7 +72,9 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.util.*; import java.util.*;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@ -122,6 +126,8 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
private WeixinNoticeProducer weixinNoticeProducer; private WeixinNoticeProducer weixinNoticeProducer;
@Resource @Resource
private RedissonClient redissonClient; private RedissonClient redissonClient;
@Resource
private MerchantDetailsService merchantDetailsService;
private static final String LOCK_KEY = "cart:check:stock:lock"; private static final String LOCK_KEY = "cart:check:stock:lock";
private static final String STOCK_LOCK_KEY = "cart:do:stock:lock"; private static final String STOCK_LOCK_KEY = "cart:do:stock:lock";
@ -419,27 +425,44 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
Map<String, Object> map = new LinkedHashMap<>(); Map<String, Object> map = new LinkedHashMap<>();
switch (PayTypeEnum.toType(param.getPaytype())){ switch (PayTypeEnum.toType(param.getPaytype())){
case WEIXIN: case WEIXIN:
if(AppFromEnum.WEIXIN_H5.getValue().equals(param.getFrom())){ if(AppFromEnum.H5.getValue().equals(param.getFrom())){
MerchantPayOrder payOrder = new MerchantPayOrder("3", "MWEB", "h5商品购买", MerchantPayOrder payOrder = new MerchantPayOrder("4", "MWEB", "h5商品购买",
"h5商品购买", orderInfo.getPayPrice(), param.getUni()); "h5商品购买", orderInfo.getPayPrice(), param.getUni());
map.put("data",manager.getOrderInfo(payOrder));
Map<String, Object> payOrderInfo = manager.getOrderInfo(payOrder);
MerchantDetailsDO merchantDetailsDO = merchantDetailsService.getMerchantDetails("4");
//System.out.println("merchantDetailsDO:"+merchantDetailsDO);
String url = merchantDetailsDO.getReturnUrl();
String newUrl = "";
try {
newUrl = String.format("%s%s", payOrderInfo.get("mweb_url"), "&redirect_url=" + URLEncoder.encode(url,"UTF-8"));
} catch (UnsupportedEncodingException e) {
log.error(e.getMessage());
// e.printStackTrace();
}
map.put("data",newUrl);
} else if(AppFromEnum.ROUNTINE.getValue().equals(param.getFrom())){ } else if(AppFromEnum.ROUNTINE.getValue().equals(param.getFrom())){
MerchantPayOrder payOrder = new MerchantPayOrder("3", "JSAPI", "小程序商品购买", MerchantPayOrder payOrder = new MerchantPayOrder("3", "JSAPI", "小程序商品购买",
"小程序商品购买", orderInfo.getPayPrice(), param.getUni()); "小程序商品购买", orderInfo.getPayPrice(), param.getUni());
payOrder.setOpenid(memberUserDO.getWxProfile().getRoutineOpenid());
//System.out.println(manager.getOrderInfo(payOrder));
payOrder.setOpenid(memberUserDO.getRoutineOpenid());
// System.out.println("payOrder:"+manager.getOrderInfo(payOrder));
//log.error();
map.put("data",manager.getOrderInfo(payOrder)); map.put("data",manager.getOrderInfo(payOrder));
}else if(AppFromEnum.APP.getValue().equals(param.getFrom())){ }else if(AppFromEnum.APP.getValue().equals(param.getFrom())){
//app支付 //app支付
MerchantPayOrder payOrder = new MerchantPayOrder("3", "APP", "APP商品购买", MerchantPayOrder payOrder = new MerchantPayOrder("5", "APP", "APP商品购买",
"APP5商品购买", orderInfo.getPayPrice(), param.getUni()); "APP5商品购买", orderInfo.getPayPrice(), param.getUni());
map.put("data",manager.getOrderInfo(payOrder)); map.put("data",manager.app(payOrder));
}else{//公众号 }else{//公众号
//detailId 是后台数据库添加当服务商id //detailId 是后台数据库添加当服务商id
MerchantPayOrder payOrder = new MerchantPayOrder("3", "JSAPI", "公众号商品购买", MerchantPayOrder payOrder = new MerchantPayOrder("3", "JSAPI", "公众号商品购买",
"公众号商品购买", orderInfo.getPayPrice(), param.getUni()); "公众号商品购买", orderInfo.getPayPrice(), param.getUni());
payOrder.setOpenid(memberUserDO.getWxProfile().getOpenid()); payOrder.setOpenid(memberUserDO.getOpenid());
map.put("data",manager.getOrderInfo(payOrder)); map.put("data",manager.getOrderInfo(payOrder));
} }
break; break;
@ -448,11 +471,16 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
map.put("status","ok"); map.put("status","ok");
break; break;
case ALI: case ALI:
//小程序支付 //h5支付
MerchantPayOrder payOrder = new MerchantPayOrder("1", "MINAPP", "小程序商品购买", if(AppFromEnum.H5.getValue().equals(param.getFrom())){
"小程序商品购买", orderInfo.getPayPrice(), param.getUni()); MerchantPayOrder payOrder = new MerchantPayOrder("1", "WAP", "支付宝H5商品购买",
// payOrder.setOpenid(memberUserDO.getWxProfile().getOpenid()); "h5商品购买", orderInfo.getPayPrice(), param.getUni());
map.put("data",manager.getOrderInfo(payOrder)); map.put("data",manager.toPay(payOrder));
}else if(AppFromEnum.APP.getValue().equals(param.getFrom())){
MerchantPayOrder payOrder = new MerchantPayOrder("1", "APP", "支付宝APP商品购买",
"支付宝APP5商品购买", orderInfo.getPayPrice(), param.getUni());
map.put("data",manager.app(payOrder));
}
default: default:
} }
@ -922,7 +950,7 @@ public class AppStoreOrderServiceImpl extends ServiceImpl<StoreOrderMapper,Store
refundOrder.setOrderDate(new Date()); refundOrder.setOrderDate(new Date());
refundOrder.setRefundAmount(price); refundOrder.setRefundAmount(price);
refundOrder.setRefundNo(refundNo); refundOrder.setRefundNo(refundNo);
refundOrder.setTotalAmount(orderQueryVo.getTotalPrice()); refundOrder.setTotalAmount(orderQueryVo.getPayPrice());
refundOrder.setOutTradeNo(orderQueryVo.getOrderId()); refundOrder.setOutTradeNo(orderQueryVo.getOrderId());
RefundResult refundResult = null; RefundResult refundResult = null;
if(PayTypeEnum.WEIXIN.getValue().equals(orderQueryVo.getPayType())) { if(PayTypeEnum.WEIXIN.getValue().equals(orderQueryVo.getPayType())) {

View File

@ -25,7 +25,7 @@ public class AppStoreProductQueryParam extends QueryParam {
@Schema(description = "分类ID", required = true) @Schema(description = "分类ID", required = true)
private String sid; private String sid;
@Schema(description = "是否新品,不为空的字符串即可", required = true) @Schema(description = "是否新品,不为空的字符串即可,为空不查询", required = true)
private String news; private String news;
@Schema(description = "是否积分兑换商品", required = true) @Schema(description = "是否积分兑换商品", required = true)
@ -33,4 +33,7 @@ public class AppStoreProductQueryParam extends QueryParam {
@Schema(description = "关键字", required = true) @Schema(description = "关键字", required = true)
private String keyword; private String keyword;
@Schema(description = "按照销量排序,不为空表示查询,为空不查询", required = true)
private String sales;
} }

View File

@ -148,6 +148,12 @@ public class AppStoreProductServiceImpl extends ServiceImpl<StoreProductMapper,S
wrapper.eq(StoreProductDO::getIsNew, ShopCommonEnum.IS_NEW_1.getValue()); wrapper.eq(StoreProductDO::getIsNew, ShopCommonEnum.IS_NEW_1.getValue());
} }
//销量查询
if (StrUtil.isNotBlank(productQueryParam.getSales()) &&
!ShopConstants.YSHOP_ZERO.equals(productQueryParam.getSales())) {
wrapper.orderByDesc(StoreProductDO::getSales);
}
Page<StoreProductDO> pageModel = new Page<>(productQueryParam.getPage(), Page<StoreProductDO> pageModel = new Page<>(productQueryParam.getPage(),
productQueryParam.getLimit()); productQueryParam.getLimit());

View File

@ -533,6 +533,10 @@ public class StoreProductServiceImpl extends ServiceImpl<StoreProductMapper,Stor
StoreProductAttrResultDO storeProductAttrResult = storeProductAttrResultService StoreProductAttrResultDO storeProductAttrResult = storeProductAttrResultService
.getOne(Wrappers.<StoreProductAttrResultDO>lambdaQuery() .getOne(Wrappers.<StoreProductAttrResultDO>lambdaQuery()
.eq(StoreProductAttrResultDO::getProductId,id).last("limit 1")); .eq(StoreProductAttrResultDO::getProductId,id).last("limit 1"));
if(storeProductAttrResult == null) {
map.put("productInfo",productDto);
return map;
}
JSONObject result = JSON.parseObject(storeProductAttrResult.getResult()); JSONObject result = JSON.parseObject(storeProductAttrResult.getResult());
List<StoreProductAttrValueDO> attrValues = storeProductAttrValueService.list(new LambdaQueryWrapper<StoreProductAttrValueDO>().eq(StoreProductAttrValueDO::getProductId, id)); List<StoreProductAttrValueDO> attrValues = storeProductAttrValueService.list(new LambdaQueryWrapper<StoreProductAttrValueDO>().eq(StoreProductAttrValueDO::getProductId, id));
List<ProductFormatDto> productFormatDtos =attrValues.stream().map(i ->{ List<ProductFormatDto> productFormatDtos =attrValues.stream().map(i ->{

View File

@ -19,6 +19,7 @@ public interface ErrorCodeConstants {
ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期"); ErrorCode AUTH_TOKEN_EXPIRED = new ErrorCode(1004003004, "Token 已经过期");
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定"); ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1004003005, "未绑定账号,需要进行绑定");
ErrorCode AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1004003006, "获得手机号失败"); ErrorCode AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR = new ErrorCode(1004003006, "获得手机号失败");
ErrorCode MINI_AUTH_LOGIN_BAD = new ErrorCode(1004004002, "登录失败,请联系管理员");
// ========== 用户收件地址 1004004000 ========== // ========== 用户收件地址 1004004000 ==========
ErrorCode USER_ADDRESS_NOT_EXISTS = new ErrorCode(1004004000, "用户收件地址不存在"); ErrorCode USER_ADDRESS_NOT_EXISTS = new ErrorCode(1004004000, "用户收件地址不存在");

View File

@ -43,7 +43,7 @@ public class AppUserAddressQueryVo implements Serializable {
private String detail; private String detail;
@Schema(description = "邮编", required = true, example = "24169") @Schema(description = "邮编", required = true, example = "24169")
private Integer postCode; private String postCode;
@Schema(description = "经度", required = true, example = "24169") @Schema(description = "经度", required = true, example = "24169")
private String longitude; private String longitude;

View File

@ -170,9 +170,16 @@ public class MemberUserDO extends TenantBaseDO {
*/ */
private String loginType; private String loginType;
//公众号openid
private String openid;
//小程序openid
private String routineOpenid;
/** 微信用户json信息 */ /** 微信用户json信息 */
@TableField(typeHandler = FastjsonTypeHandler.class) @TableField(typeHandler = FastjsonTypeHandler.class)
@Deprecated
private WechatUserDto wxProfile; private WechatUserDto wxProfile;
} }

View File

@ -1,9 +1,11 @@
package co.yixiang.yshop.module.member.service.auth; package co.yixiang.yshop.module.member.service.auth;
import cn.binarywang.wx.miniapp.api.WxMaService; import cn.binarywang.wx.miniapp.api.WxMaService;
import cn.binarywang.wx.miniapp.bean.WxMaJscode2SessionResult;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo; import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import co.yixiang.yshop.framework.common.enums.CommonStatusEnum; import co.yixiang.yshop.framework.common.enums.CommonStatusEnum;
import co.yixiang.yshop.framework.common.enums.UserTypeEnum; import co.yixiang.yshop.framework.common.enums.UserTypeEnum;
import co.yixiang.yshop.framework.common.util.monitor.TracerUtils; import co.yixiang.yshop.framework.common.util.monitor.TracerUtils;
@ -29,6 +31,7 @@ import co.yixiang.yshop.module.system.enums.sms.SmsSceneEnum;
import co.yixiang.yshop.module.system.enums.social.SocialTypeEnum; import co.yixiang.yshop.module.system.enums.social.SocialTypeEnum;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
@ -39,6 +42,7 @@ import java.util.Objects;
import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception; import static co.yixiang.yshop.framework.common.exception.util.ServiceExceptionUtil.exception;
import static co.yixiang.yshop.framework.common.util.servlet.ServletUtils.getClientIP; import static co.yixiang.yshop.framework.common.util.servlet.ServletUtils.getClientIP;
import static co.yixiang.yshop.module.member.enums.ErrorCodeConstants.*; import static co.yixiang.yshop.module.member.enums.ErrorCodeConstants.*;
import static co.yixiang.yshop.module.member.enums.ErrorCodeConstants.MINI_AUTH_LOGIN_BAD;
/** /**
* 会员的认证 Service 接口 * 会员的认证 Service 接口
@ -130,19 +134,34 @@ public class MemberAuthServiceImpl implements MemberAuthService {
try { try {
phoneNumberInfo = wxMaService.getUserService().getNewPhoneNoInfo(reqVO.getPhoneCode()); phoneNumberInfo = wxMaService.getUserService().getNewPhoneNoInfo(reqVO.getPhoneCode());
} catch (Exception exception) { } catch (Exception exception) {
log.error(exception.getMessage());
throw exception(AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR); throw exception(AUTH_WEIXIN_MINI_APP_PHONE_CODE_ERROR);
} }
// 获得获得注册用户 // 用户已经存在
MemberUserDO user = userService.createUserIfAbsent(phoneNumberInfo.getPurePhoneNumber(), getClientIP(), MemberUserDO memberUserDO = userMapper.selectByMobile(phoneNumberInfo.getPhoneNumber());
LoginTypeEnum.WXAPP.getValue()); if (memberUserDO == null || StrUtil.isBlank(memberUserDO.getRoutineOpenid())) {
Assert.notNull(user, "获取用户失败,结果为空");
// 绑定社交用户 WxMaJscode2SessionResult session = null;
socialUserApi.bindSocialUser(new SocialUserBindReqDTO(user.getId(), getUserType().getValue(), try {
SocialTypeEnum.WECHAT_MINI_APP.getType(), reqVO.getLoginCode(), "")); session = wxMaService.getUserService().getSessionInfo(reqVO.getLoginCode());
} catch (WxErrorException e) {
log.error(e.getMessage());
throw exception(MINI_AUTH_LOGIN_BAD);
}
if(memberUserDO == null){
// 获得获得注册用户
memberUserDO = userService.createUserIfAbsent(phoneNumberInfo.getPhoneNumber(), getClientIP(),
LoginTypeEnum.WXAPP.getValue());
memberUserDO.setNickname("yshop用户_" + memberUserDO.getId());
}
memberUserDO.setRoutineOpenid(session.getOpenid());
userMapper.updateById(memberUserDO);
}
// 创建 Token 令牌,记录登录日志 // 创建 Token 令牌,记录登录日志
return createTokenAfterLoginSuccess(user, user.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL); return createTokenAfterLoginSuccess(memberUserDO, memberUserDO.getMobile(), LoginLogTypeEnum.LOGIN_SOCIAL);
} }
private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile, LoginLogTypeEnum logType) { private AppAuthLoginRespVO createTokenAfterLoginSuccess(MemberUserDO user, String mobile, LoginLogTypeEnum logType) {

View File

@ -26,6 +26,10 @@ public class MerchantPayServiceConfigurer implements PayServiceConfigurer {
@Resource @Resource
private JdbcTemplate jdbcTemplate; private JdbcTemplate jdbcTemplate;
@Resource
private AliPayMessageHandler aliPayMessageHandler;
@Resource
private WxPayMessageHandler wxPayMessageHandler;
/** /**
* 商户配置 * 商户配置
@ -49,7 +53,7 @@ public class MerchantPayServiceConfigurer implements PayServiceConfigurer {
public void configure(PayMessageConfigurer configurer) { public void configure(PayMessageConfigurer configurer) {
PaymentPlatform aliPaymentPlatform = PaymentPlatforms.getPaymentPlatform(AliPaymentPlatform.PLATFORM_NAME); PaymentPlatform aliPaymentPlatform = PaymentPlatforms.getPaymentPlatform(AliPaymentPlatform.PLATFORM_NAME);
PaymentPlatform wxPaymentPlatform = PaymentPlatforms.getPaymentPlatform(WxPaymentPlatform.PLATFORM_NAME); PaymentPlatform wxPaymentPlatform = PaymentPlatforms.getPaymentPlatform(WxPaymentPlatform.PLATFORM_NAME);
configurer.addHandler(aliPaymentPlatform, new AliPayMessageHandler()); configurer.addHandler(aliPaymentPlatform, aliPayMessageHandler);
configurer.addHandler(wxPaymentPlatform, new WxPayMessageHandler()); configurer.addHandler(wxPaymentPlatform, wxPayMessageHandler);
} }
} }

View File

@ -6,6 +6,7 @@ import com.egzosn.pay.ali.bean.AliPayMessage;
import com.egzosn.pay.common.api.PayMessageHandler; import com.egzosn.pay.common.api.PayMessageHandler;
import com.egzosn.pay.common.bean.PayOutMessage; import com.egzosn.pay.common.bean.PayOutMessage;
import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.exception.PayErrorException;
import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Map; import java.util.Map;
@ -15,7 +16,7 @@ import java.util.Map;
* @author hupeng * @author hupeng
* @date 2023/7/15 * @date 2023/7/15
*/ */
//@Component @Component
public class AliPayMessageHandler implements PayMessageHandler<AliPayMessage, AliPayService> { public class AliPayMessageHandler implements PayMessageHandler<AliPayMessage, AliPayService> {
@Resource @Resource

View File

@ -7,6 +7,7 @@ import com.egzosn.pay.common.bean.PayOutMessage;
import com.egzosn.pay.common.exception.PayErrorException; import com.egzosn.pay.common.exception.PayErrorException;
import com.egzosn.pay.wx.bean.WxPayMessage; import com.egzosn.pay.wx.bean.WxPayMessage;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.util.Map; import java.util.Map;
@ -16,6 +17,7 @@ import java.util.Map;
* @author hupeng * @author hupeng
* @date 2023/7/15 * @date 2023/7/15
*/ */
@Component
@Slf4j @Slf4j
public class WxPayMessageHandler implements PayMessageHandler<WxPayMessage, PayService> { public class WxPayMessageHandler implements PayMessageHandler<WxPayMessage, PayService> {

View File

@ -12,8 +12,12 @@ import javax.validation.constraints.*;
@Data @Data
public class MerchantDetailsBaseVO { public class MerchantDetailsBaseVO {
private String detailsId;
private String title;
@Schema(description = "支付类型(支付渠道) 详情查看com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform对应子类aliPay 支付宝, wxPay微信..等等", required = true, example = "2") @Schema(description = "支付类型(支付渠道) 详情查看com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform对应子类aliPay 支付宝, wxPay微信..等等", required = true, example = "2")
@NotNull(message = "支付类型(支付渠道) 详情查看com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform对应子类aliPay 支付宝, wxPay微信..等等不能为空") @NotNull(message = "支付类型(支付渠道)不能为空")
private String payType; private String payType;
@Schema(description = "应用id", example = "1718") @Schema(description = "应用id", example = "1718")
@ -44,7 +48,7 @@ public class MerchantDetailsBaseVO {
private String returnUrl; private String returnUrl;
@Schema(description = "签名方式,目前已实现多种签名方式详情查看com.egzosn.pay.common.util.sign.encrypt。MD5,RSA等等", required = true, example = "1") @Schema(description = "签名方式,目前已实现多种签名方式详情查看com.egzosn.pay.common.util.sign.encrypt。MD5,RSA等等", required = true, example = "1")
@NotNull(message = "签名方式,目前已实现多种签名方式详情查看com.egzosn.pay.common.util.sign.encrypt。MD5,RSA等等不能为空") @NotNull(message = "签名方式不能为空")
private String signType; private String signType;
@Schema(description = "收款账号,暂时只有支付宝部分使用,可根据开发者自行使用") @Schema(description = "收款账号,暂时只有支付宝部分使用,可根据开发者自行使用")
@ -57,7 +61,6 @@ public class MerchantDetailsBaseVO {
private String subMchId; private String subMchId;
@Schema(description = "编码类型大部分为utf-8", required = true) @Schema(description = "编码类型大部分为utf-8", required = true)
@NotNull(message = "编码类型大部分为utf-8不能为空")
private String inputCharset; private String inputCharset;
@Schema(description = "是否为测试环境: 0 否1 测试环境", required = true) @Schema(description = "是否为测试环境: 0 否1 测试环境", required = true)

View File

@ -3,6 +3,8 @@ package co.yixiang.yshop.module.pay.controller.admin.merchantdetails.vo;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.*; import lombok.*;
import java.time.LocalDateTime;
@Schema(description = "管理后台 - 支付服务商配置 Response VO") @Schema(description = "管理后台 - 支付服务商配置 Response VO")
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ -12,4 +14,6 @@ public class MerchantDetailsRespVO extends MerchantDetailsBaseVO {
@Schema(description = "列表id", required = true, example = "17552") @Schema(description = "列表id", required = true, example = "17552")
private String detailsId; private String detailsId;
private LocalDateTime createTime;
} }

View File

@ -24,6 +24,8 @@ public class MerchantDetailsDO extends BaseDO {
*/ */
@TableId(type = IdType.INPUT) @TableId(type = IdType.INPUT)
private String detailsId; private String detailsId;
private String title;
/** /**
* 支付类型(支付渠道) 详情查看com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform对应子类aliPay 支付宝, wxPay微信..等等 * 支付类型(支付渠道) 详情查看com.egzosn.pay.spring.boot.core.merchant.PaymentPlatform对应子类aliPay 支付宝, wxPay微信..等等
*/ */

View File

@ -12,8 +12,8 @@ COPY ./target/yshop-server.jar app.jar
## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖 ## 设置 JAVA_OPTS 环境变量,可通过 docker run -e "JAVA_OPTS=" 进行覆盖
ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m" ENV TZ=Asia/Shanghai JAVA_OPTS="-Xms512m -Xmx512m"
## 暴露后端项目的 48080 端口 ## 暴露后端项目的 48082 端口
EXPOSE 48080 EXPOSE 48082
## 启动后端项目 ## 启动后端项目
CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar CMD java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar app.jar

View File

@ -1,5 +1,5 @@
server: server:
port: 48080 port: 48082
--- #################### 数据库相关配置 #################### --- #################### 数据库相关配置 ####################

View File

@ -1,5 +1,5 @@
server: server:
port: 48080 port: 48082
--- #################### 数据库相关配置 #################### --- #################### 数据库相关配置 ####################
@ -173,8 +173,8 @@ wx:
key-prefix: wx # Redis Key 的前缀 TODO 解决下 Redis key 管理的配置 key-prefix: wx # Redis Key 的前缀 TODO 解决下 Redis key 管理的配置
http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台 http-client-type: HttpClient # 采用 HttpClient 请求微信公众号平台
miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档 miniapp: # 小程序配置(必填),参见 https://github.com/Wechat-Group/WxJava/blob/develop/spring-boot-starters/wx-java-miniapp-spring-boot-starter/README.md 文档
appid: wx63c280fe3248a3e7 appid: wx604d2ea4702620d2
secret: 6f270509224a7ae1296bbf1c8cb97aed secret: 0beb4dad95fbd97cbaf2a0a4dec51575
config-storage: config-storage:
type: RedisTemplate # 采用 RedisTemplate 操作 Redis会自动从 Spring 中获取 type: RedisTemplate # 采用 RedisTemplate 操作 Redis会自动从 Spring 中获取
key-prefix: wa # Redis Key 的前缀 TODO yshop解决下 Redis key 管理的配置 key-prefix: wa # Redis Key 的前缀 TODO yshop解决下 Redis key 管理的配置
@ -193,9 +193,6 @@ yshop:
exclude-urls: # 如下两个 url仅仅是为了演示去掉配置也没关系 exclude-urls: # 如下两个 url仅仅是为了演示去掉配置也没关系
- ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求 - ${spring.boot.admin.context-path}/** # 不处理 Spring Boot Admin 的请求
- ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求 - ${management.endpoints.web.base-path}/** # 不处理 Actuator 的请求
pay:
callback-url: http://yshop.natapp1.cc/admin-api/pay/notify/callback
return-url: http://yshop.natapp1.cc/admin-api/pay/notify/return
access-log: # 访问日志的配置项 access-log: # 访问日志的配置项
enable: false enable: false
error-code: # 错误码相关配置项 error-code: # 错误码相关配置项
@ -219,6 +216,10 @@ justauth:
client-secret: ${wx.miniapp.secret} client-secret: ${wx.miniapp.secret}
ignore-check-redirect-uri: true ignore-check-redirect-uri: true
ignore-check-state: true # 微信小程序,不会使用到 state所以不进行校验 ignore-check-state: true # 微信小程序,不会使用到 state所以不进行校验
WECHAT_OPEN: #微信开发平台
client-id: 10**********6
client-secret: 1f7d08**********5b7**********29e
redirect-uri: http://oauth.xkcoding.com/demo/oauth/wechat_open/callback
cache: cache:
type: REDIS type: REDIS

View File

@ -16,7 +16,7 @@
<script> <script>
let shopOrderId = undefined; let shopOrderId = undefined;
let payOrderId = undefined; let payOrderId = undefined;
// let server = 'http://127.0.0.1:48080'; // let server = 'http://127.0.0.1:48082';
let server = 'http://niubi.natapp1.cc'; let server = 'http://niubi.natapp1.cc';
// TODO openid // TODO openid
let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0"; let openid = "ockUAwIZ-0OeMZl9ogcZ4ILrGba0";