diff --git a/pom.xml b/pom.xml index 88c8b66..a579c4f 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,18 @@ + + + com.google.apis + google-api-services-androidpublisher + v3-rev20231012-2.0.0 + + + com.google.http-client + google-http-client-jackson2 + 1.38.0 + + com.google.guava guava diff --git a/src/main/java/com/peanut/config/ShiroConfig.java b/src/main/java/com/peanut/config/ShiroConfig.java index 235a38d..027f387 100644 --- a/src/main/java/com/peanut/config/ShiroConfig.java +++ b/src/main/java/com/peanut/config/ShiroConfig.java @@ -71,6 +71,7 @@ public class ShiroConfig { filterMap.put("/pay/paypal/receivePaypalStatus","anon"); // paypal回调接口 filterMap.put("/pay/stripe/callback","anon"); // stripe回调接口 filterMap.put("/pay/stripe/transfer","anon"); // stripe中转接口 + filterMap.put("/pay/googlepay/callback","anon"); // paypal回调接口 filterMap.put("/weChat/**","anon"); filterMap.put("/book/baseArea/getAllBaseArea","anon");//登录前获取全部区域 // filterMap.put("/book/bookchaptercontent/**","anon"); diff --git a/src/main/java/com/peanut/modules/book/controller/BookController.java b/src/main/java/com/peanut/modules/book/controller/BookController.java index 57ae85c..297feec 100644 --- a/src/main/java/com/peanut/modules/book/controller/BookController.java +++ b/src/main/java/com/peanut/modules/book/controller/BookController.java @@ -18,6 +18,8 @@ import com.peanut.modules.book.service.*; import com.peanut.modules.book.vo.BookIndexVo; import com.peanut.modules.common.entity.*; import com.peanut.modules.oss.service.OssService; +import com.peanut.modules.sys.entity.SysDictDataEntity; +import com.peanut.modules.sys.service.SysDictDataService; import com.spire.doc.Document; import com.spire.doc.Section; import com.spire.doc.documents.Paragraph; @@ -78,6 +80,8 @@ public class BookController { private MedicaldesBookService medicaldesBookService; @Autowired private BookForumArticlesDao bookForumArticlesDao; + @Autowired + private SysDictDataService sysDictDataService; final ExecutorService fixedThreadPool = Executors.newFixedThreadPool(10); /** @@ -140,6 +144,9 @@ public class BookController { } book.setMedicaldesBookType(type); } + //设置海外价格级别 + SysDictDataEntity sysDictData = sysDictDataService.getById(book.getAbroadPriceId()); + book.setPriceData(sysDictData); return R.ok().put("book", book); } diff --git a/src/main/java/com/peanut/modules/book/controller/MedicaldesController.java b/src/main/java/com/peanut/modules/book/controller/MedicaldesController.java index a649322..44b7f5f 100644 --- a/src/main/java/com/peanut/modules/book/controller/MedicaldesController.java +++ b/src/main/java/com/peanut/modules/book/controller/MedicaldesController.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.peanut.common.utils.R; -import com.peanut.modules.book.entity.SysDictDataEntity; +import com.peanut.modules.sys.entity.SysDictDataEntity; import com.peanut.modules.book.service.*; import com.peanut.modules.common.entity.*; import com.peanut.modules.sys.service.SysDictDataService; diff --git a/src/main/java/com/peanut/modules/book/controller/MedicinalMaterialsController.java b/src/main/java/com/peanut/modules/book/controller/MedicinalMaterialsController.java index 1017ba9..f4e00bc 100644 --- a/src/main/java/com/peanut/modules/book/controller/MedicinalMaterialsController.java +++ b/src/main/java/com/peanut/modules/book/controller/MedicinalMaterialsController.java @@ -6,7 +6,7 @@ import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.peanut.common.utils.R; import com.peanut.modules.common.entity.MedicinalDrug; import com.peanut.modules.common.entity.MedicinalMaterials; -import com.peanut.modules.book.entity.SysDictDataEntity; +import com.peanut.modules.sys.entity.SysDictDataEntity; import com.peanut.modules.book.service.MedicinalDrugService; import com.peanut.modules.book.service.MedicinalMaterialsService; import com.peanut.modules.sys.service.SysDictDataService; diff --git a/src/main/java/com/peanut/modules/book/controller/MyUserController.java b/src/main/java/com/peanut/modules/book/controller/MyUserController.java index ec966e5..ec07dd7 100644 --- a/src/main/java/com/peanut/modules/book/controller/MyUserController.java +++ b/src/main/java/com/peanut/modules/book/controller/MyUserController.java @@ -668,7 +668,7 @@ public class MyUserController { MyUserEntity user = this.userService.getById(userId); BookBuyConfigEntity bookBuyConfigEntity = bookBuyConfigService.getById(configId); String month = bookBuyConfigEntity.getMonth(); - BigDecimal amount = new BigDecimal(bookBuyConfigEntity.getRealMoney()); + BigDecimal amount = bookBuyConfigEntity.getRealMoney(); diff --git a/src/main/java/com/peanut/modules/book/service/impl/BookServiceImpl.java b/src/main/java/com/peanut/modules/book/service/impl/BookServiceImpl.java index 69bdbe5..b73d274 100644 --- a/src/main/java/com/peanut/modules/book/service/impl/BookServiceImpl.java +++ b/src/main/java/com/peanut/modules/book/service/impl/BookServiceImpl.java @@ -15,7 +15,7 @@ import com.peanut.common.utils.FileDownloadUtil; import com.peanut.common.utils.PageUtils; import com.peanut.common.utils.Query; import com.peanut.modules.common.dao.BookDao; -import com.peanut.modules.book.entity.SysDictDataEntity; +import com.peanut.modules.sys.entity.SysDictDataEntity; import com.peanut.modules.book.service.BookChapterContentService; import com.peanut.modules.book.service.BookChapterService; import com.peanut.modules.book.service.BookService; @@ -82,6 +82,9 @@ public class BookServiceImpl extends ServiceImpl implements .apply(StringUtils.isNotBlank(authorName1), "FIND_IN_SET((SELECT id FROM author WHERE author_name LIKE concat( '%','" + authorName1 + "','%')),author_id)") ); for (BookEntity book : page.getRecords()) { + //设置海外价格级别 + SysDictDataEntity sysDictData = sysDictDataService.getById(book.getAbroadPriceId()); + book.setPriceData(sysDictData); String authorName = ""; String publisherName = ""; ArrayList list = new ArrayList<>(); diff --git a/src/main/java/com/peanut/modules/book/service/impl/PayPaymentOrderServiceImpl.java b/src/main/java/com/peanut/modules/book/service/impl/PayPaymentOrderServiceImpl.java index 43880c6..b348880 100644 --- a/src/main/java/com/peanut/modules/book/service/impl/PayPaymentOrderServiceImpl.java +++ b/src/main/java/com/peanut/modules/book/service/impl/PayPaymentOrderServiceImpl.java @@ -41,8 +41,8 @@ public class PayPaymentOrderServiceImpl extends ServiceImpl bookIds) { for (Integer i:bookIds){ - List userEbookBuyEntities = this.getBaseMapper().selectList(new LambdaQueryWrapper().eq(UserEbookBuyEntity::getUserId, userId).eq(UserEbookBuyEntity::getBookId, i)); + List userEbookBuyEntities = this.getBaseMapper().selectList(new LambdaQueryWrapper() + .eq(UserEbookBuyEntity::getUserId, userId) + .eq(UserEbookBuyEntity::getBookId, i)); if(userEbookBuyEntities.size()==0){ UserEbookBuyEntity userEbookBuyEntity = new UserEbookBuyEntity(); userEbookBuyEntity.setUserId(userId); diff --git a/src/main/java/com/peanut/modules/bookAbroad/controller/HomeController.java b/src/main/java/com/peanut/modules/bookAbroad/controller/HomeController.java index ceb177a..dcfc6d3 100644 --- a/src/main/java/com/peanut/modules/bookAbroad/controller/HomeController.java +++ b/src/main/java/com/peanut/modules/bookAbroad/controller/HomeController.java @@ -8,8 +8,11 @@ import com.peanut.common.utils.R; import com.peanut.common.utils.ShiroUtils; import com.peanut.modules.book.service.*; import com.peanut.modules.common.entity.*; +import com.peanut.modules.common.service.UserEbookVipService; import com.peanut.modules.master.service.BookAbroadToLableService; import com.peanut.modules.bookAbroad.service.BookAbroadLableService; +import com.peanut.modules.sys.entity.SysDictDataEntity; +import com.peanut.modules.sys.service.SysDictDataService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; import org.apache.http.client.utils.DateUtils; @@ -46,16 +49,25 @@ public class HomeController { private BookChapterContentService bookChapterContentService; @Autowired private BuyOrderService buyOrderService; + @Autowired + private UserEbookVipService userEbookVipService; + @Autowired + private SysDictDataService sysDictDataService; //我的图书 @RequestMapping("/getMyBooks") public R getMyBooks(@RequestBody Map params){ - MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>(); - wrapper.leftJoin(BookEntity.class,BookEntity::getId,UserEbookBuyEntity::getBookId); - wrapper.eq(UserEbookBuyEntity::getUserId,ShiroUtils.getUId()); + MPJLambdaWrapper wrapper = new MPJLambdaWrapper<>(); wrapper.select(BookEntity::getId,BookEntity::getName,BookEntity::getImages); - wrapper.groupBy(UserEbookBuyEntity::getBookId); - Page p = userEbookBuyService.pageMaps(new Page<>( + long c = userEbookVipService.count(new LambdaQueryWrapper().eq(UserEbookVip::getUserId,ShiroUtils.getUId())); + if (c>0){ + wrapper.and(t->t.eq(BookEntity::getIsVip,1) + .or().exists("select book_id from user_ebook_buy where book_id = t.id and user_id = "+ShiroUtils.getUId()+"")); + }else { + wrapper.leftJoin(UserEbookBuyEntity.class,UserEbookBuyEntity::getBookId,BookEntity::getId); + wrapper.eq(UserEbookBuyEntity::getUserId,ShiroUtils.getUId()); + } + Page p = bookService.pageMaps(new Page<>( Long.parseLong(params.get("current").toString()), Long.parseLong(params.get("limit").toString())),wrapper); List> list = p.getRecords(); for (Map map:list) { @@ -152,9 +164,10 @@ public class HomeController { wrapper.leftJoin(BookEntity.class,BookEntity::getId,BookAbroadToLable::getBookId); wrapper.selectAs(BookAbroadToLable::getId,"toLableId"); wrapper.selectAs(BookEntity::getId,"bookId"); - wrapper.selectAs(BookEntity::getAbroadPrice,"abroadPrice"); + wrapper.selectAs(BookEntity::getAbroadPriceId,"abroadPriceId"); wrapper.select(BookEntity::getImages); wrapper.select(BookEntity::getName); + wrapper.select(BookEntity::getIsVip); wrapper.eq(BookAbroadToLable::getLableId,params.get("lableId")); wrapper.orderByAsc(BookAbroadToLable::getSort); List> list = toLableService.listMaps(wrapper); @@ -168,6 +181,15 @@ public class HomeController { map.put("readCount",readCount); map.put("buyCount",buyCount); map.put("listenCount",listenCount); + map.put("isBuy",false); + long count = userEbookBuyService.count(new LambdaQueryWrapper() + .eq(UserEbookBuyEntity::getUserId,ShiroUtils.getUId()) + .eq(UserEbookBuyEntity::getBookId,map.get("bookId"))); + if (count > 0) { + map.put("isBuy",true); + } + SysDictDataEntity sysDictData = sysDictDataService.getById(map.get("abroadPriceId").toString()); + map.put("sysDictData",sysDictData); } return R.ok().put("bookList",list); } @@ -184,6 +206,8 @@ public class HomeController { if (count > 0) { bookEntity.setIsBuy(true); } + SysDictDataEntity sysDictData = sysDictDataService.getById(bookEntity.getAbroadPriceId()); + bookEntity.setPriceData(sysDictData); return R.ok().put("bookInfo",bookEntity); } @@ -321,6 +345,14 @@ public class HomeController { return R.ok().put("orders",orders); } + //订单列表 + @RequestMapping("/getVipInfo") + public R getVipInfo(){ + UserEbookVip vip = userEbookVipService.getOne(new LambdaQueryWrapper() + .eq(UserEbookVip::getUserId,ShiroUtils.getUId())); + return R.ok().put("vipInfo",vip); + } + diff --git a/src/main/java/com/peanut/modules/bookAbroad/controller/OrderController.java b/src/main/java/com/peanut/modules/bookAbroad/controller/OrderController.java index 982b7b4..51f0ac4 100644 --- a/src/main/java/com/peanut/modules/bookAbroad/controller/OrderController.java +++ b/src/main/java/com/peanut/modules/bookAbroad/controller/OrderController.java @@ -58,46 +58,20 @@ public class OrderController { } buyOrder.setUserId(ShiroUtils.getUId()); buyOrder.setCome(3);//3 海外读书 - BookEntity bookEntity = bookService.getById(buyOrder.getAbroadBookId()); BigDecimal totalPrice = buyOrder.getOrderMoney(); - //校验价格 - if (totalPrice.compareTo(new BigDecimal(0))<=0){ - return R.error("The order price cannot be 0"); - } - if (Constants.PAYMENT_METHOD_VIRTUAL.equals(buyOrder.getPaymentMethod())) { - if (totalPrice.compareTo(bookEntity.getAbroadPrice().multiply(new BigDecimal(10)))!=0){ - return R.error("Abnormal order price"); - } + if ("abroadBook".equals(buyOrder.getOrderType())){ + BookEntity bookEntity = bookService.getById(buyOrder.getAbroadBookId()); + buyOrder.setRealMoney(totalPrice); + String bookName = bookEntity.getName(); + buyOrder.setRemark("Purchase the e-book '"+bookName+"'"); }else { - if (totalPrice.compareTo(bookEntity.getAbroadPrice())!=0){ - return R.error("Abnormal order price"); - } + buyOrder.setRealMoney(totalPrice); + buyOrder.setRemark("Purchase VIP"); } - buyOrder.setRealMoney(totalPrice); - String bookName = bookEntity.getName(); - buyOrder.setRemark("Purchase the e-book '"+bookName+"'"); buyOrder.setOrderStatus("0"); - buyOrder.setOrderType("abroadBook"); String timeId = IdWorker.getTimeId().substring(0, 32); buyOrder.setOrderSn(timeId); buyOrderService.save(buyOrder); - // 1. 虚拟币支付 - if (Constants.PAYMENT_METHOD_VIRTUAL.equals(buyOrder.getPaymentMethod())) { - MyUserEntity user = ShiroUtils.getUser(); - if (user.getPeanutCoin().compareTo(totalPrice)>=0){ - //更新虚拟币 - user.setPeanutCoin(user.getPeanutCoin().subtract(totalPrice)); - myUserService.updateById(user); - //更新订单状态 - buyOrderService.updateOrderStatus(user.getId(), buyOrder.getOrderSn(), "2"); - //记录用户虚拟币消费 - transactionDetailsService.recordTransaction(buyOrder, user, totalPrice); - //开通电子书权限 - userEbookBuyService.addBookForUser(user.getId(), Arrays.asList(buyOrder.getAbroadBookId())); - }else { - return R.error(500, "Insufficient Balance!"); - } - } rabbitTemplate.convertAndSend( DelayQueueConfig.ORDER_TO_BE_PAY_EXCHANGE, DelayQueueConfig.ORDER_TO_BE_PAY_ROUTING_KEY, diff --git a/src/main/java/com/peanut/modules/bookAbroad/controller/VisitorController.java b/src/main/java/com/peanut/modules/bookAbroad/controller/VisitorController.java index f4bc123..76bf76d 100644 --- a/src/main/java/com/peanut/modules/bookAbroad/controller/VisitorController.java +++ b/src/main/java/com/peanut/modules/bookAbroad/controller/VisitorController.java @@ -77,7 +77,6 @@ public class VisitorController { wrapper.leftJoin(BookEntity.class,BookEntity::getId,BookAbroadToLable::getBookId); wrapper.selectAs(BookAbroadToLable::getId,"toLableId"); wrapper.selectAs(BookEntity::getId,"bookId"); - wrapper.selectAs(BookEntity::getAbroadPrice,"abroadPrice"); wrapper.select(BookEntity::getImages); wrapper.select(BookEntity::getName); wrapper.eq(BookAbroadToLable::getLableId,params.get("lableId")); @@ -93,6 +92,7 @@ public class VisitorController { map.put("readCount",readCount); map.put("buyCount",buyCount); map.put("listenCount",listenCount); + map.put("abroadPrice",9.9); } return R.ok().put("bookList",list); } diff --git a/src/main/java/com/peanut/modules/common/controller/MedicaldesController.java b/src/main/java/com/peanut/modules/common/controller/MedicaldesController.java index 48a73f0..eea2b74 100644 --- a/src/main/java/com/peanut/modules/common/controller/MedicaldesController.java +++ b/src/main/java/com/peanut/modules/common/controller/MedicaldesController.java @@ -9,6 +9,7 @@ import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.peanut.common.utils.R; import com.peanut.modules.common.entity.*; import com.peanut.modules.common.service.*; +import com.peanut.modules.sys.entity.SysDictDataEntity; import com.peanut.modules.sys.service.SysDictDataService; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang.StringUtils; @@ -53,8 +54,8 @@ public class MedicaldesController { */ @RequestMapping(path = "/typeList") public R typeList(String label) { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); - wrapper.eq(com.peanut.modules.book.entity.SysDictDataEntity::getDictLabel,label); + LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); + wrapper.eq(SysDictDataEntity::getDictLabel,label); return R.ok().put("result",sysDictDataService.list(wrapper)); } @@ -155,10 +156,10 @@ public class MedicaldesController { } //国际医师可能来自国外在省市里加入外国 - public List getCounts() { - LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); - wrapper.eq(com.peanut.modules.book.entity.SysDictDataEntity::getDictLabel,"inheritPro"); - List dataList = sysDictDataService.list(wrapper); + public List getCounts() { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper(); + wrapper.eq(SysDictDataEntity::getDictLabel,"inheritPro"); + List dataList = sysDictDataService.list(wrapper); return dataList; } @@ -232,10 +233,10 @@ public class MedicaldesController { @RequestMapping(path = "/getCityByPro") public R getCityByPro(@RequestParam("provId") Integer provId) { List prov = new ArrayList<>(); - List list = getCounts(); + List list = getCounts(); boolean flag = false; if (list != null && list.size() > 0) { - for (com.peanut.modules.book.entity.SysDictDataEntity data:list) { + for (SysDictDataEntity data:list) { if (provId==Integer.parseInt(data.getDictType())){ prov.addAll(getCityList(data.getDictValue(),Integer.parseInt(data.getDictType()))); flag = true; diff --git a/src/main/java/com/peanut/modules/common/dao/PayGoogleOrderDao.java b/src/main/java/com/peanut/modules/common/dao/PayGoogleOrderDao.java new file mode 100644 index 0000000..b57994f --- /dev/null +++ b/src/main/java/com/peanut/modules/common/dao/PayGoogleOrderDao.java @@ -0,0 +1,9 @@ +package com.peanut.modules.common.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.peanut.modules.common.entity.PayGoogleOrder; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface PayGoogleOrderDao extends BaseMapper { +} diff --git a/src/main/java/com/peanut/modules/common/dao/UserEbookVipDao.java b/src/main/java/com/peanut/modules/common/dao/UserEbookVipDao.java new file mode 100644 index 0000000..7c2b976 --- /dev/null +++ b/src/main/java/com/peanut/modules/common/dao/UserEbookVipDao.java @@ -0,0 +1,9 @@ +package com.peanut.modules.common.dao; + +import com.github.yulichang.base.MPJBaseMapper; +import com.peanut.modules.common.entity.UserEbookVip; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UserEbookVipDao extends MPJBaseMapper { +} diff --git a/src/main/java/com/peanut/modules/common/entity/BookBuyConfigEntity.java b/src/main/java/com/peanut/modules/common/entity/BookBuyConfigEntity.java index 4ba98a6..03d911e 100644 --- a/src/main/java/com/peanut/modules/common/entity/BookBuyConfigEntity.java +++ b/src/main/java/com/peanut/modules/common/entity/BookBuyConfigEntity.java @@ -5,6 +5,7 @@ import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; import java.io.Serializable; +import java.math.BigDecimal; import java.util.Date; import lombok.Data; @@ -36,11 +37,11 @@ public class BookBuyConfigEntity implements Serializable { /** * 真实价格 */ - private String realMoney; + private BigDecimal realMoney; /** * 金额 */ - private String money; + private BigDecimal money; /** * 赠送积分 */ diff --git a/src/main/java/com/peanut/modules/common/entity/BookEntity.java b/src/main/java/com/peanut/modules/common/entity/BookEntity.java index 0e7ac93..d60d903 100644 --- a/src/main/java/com/peanut/modules/common/entity/BookEntity.java +++ b/src/main/java/com/peanut/modules/common/entity/BookEntity.java @@ -7,6 +7,7 @@ import java.io.Serializable; import java.util.Date; import java.util.List; +import com.peanut.modules.sys.entity.SysDictDataEntity; import lombok.Data; /** @@ -76,7 +77,9 @@ public class BookEntity implements Serializable { /** * 海外价格 */ - private BigDecimal abroadPrice; + private String abroadPriceId; + @TableField(exist = false) + private SysDictDataEntity priceData; /** * 价格 */ diff --git a/src/main/java/com/peanut/modules/common/entity/BuyOrder.java b/src/main/java/com/peanut/modules/common/entity/BuyOrder.java index 7e2383b..1bfb96d 100644 --- a/src/main/java/com/peanut/modules/common/entity/BuyOrder.java +++ b/src/main/java/com/peanut/modules/common/entity/BuyOrder.java @@ -67,11 +67,11 @@ public class BuyOrder implements Serializable { */ private String address; /** - * 订单来源,0疯子读书1国学众妙之门2医学吴门医述3海外读书 + * 订单来源 3海外读书 */ private Integer come; /** - * 支付方式 1微信,2支付宝,3ios内购 ,4虚拟币 5PayPal + * 支付方式 3ios内购,4.疯币,5谷歌内购 */ private String paymentMethod; /** @@ -149,7 +149,7 @@ public class BuyOrder implements Serializable { private String buyType; /** - * vip order point abroadBook offlineActivity + * point abroadBook abroadVip */ private String orderType; @@ -167,6 +167,8 @@ public class BuyOrder implements Serializable { private Integer abroadBookId;//海外读书购买书籍id + private Integer abroadVipId;//海外vipid + private Integer offlineActivityId;//线下活动id /** diff --git a/src/main/java/com/peanut/modules/common/entity/MedicaldesBook.java b/src/main/java/com/peanut/modules/common/entity/MedicaldesBook.java index 1c23262..7077330 100644 --- a/src/main/java/com/peanut/modules/common/entity/MedicaldesBook.java +++ b/src/main/java/com/peanut/modules/common/entity/MedicaldesBook.java @@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableLogic; import com.baomidou.mybatisplus.annotation.TableName; +import com.peanut.modules.sys.entity.SysDictDataEntity; import lombok.Data; import java.io.Serializable; @@ -17,7 +18,7 @@ public class MedicaldesBook implements Serializable { @TableField(exist = false) private BookEntity book; @TableField(exist = false) - private com.peanut.modules.book.entity.SysDictDataEntity sysDictData; + private SysDictDataEntity sysDictData; @TableId private Integer id; diff --git a/src/main/java/com/peanut/modules/common/entity/PayGoogleOrder.java b/src/main/java/com/peanut/modules/common/entity/PayGoogleOrder.java new file mode 100644 index 0000000..aad3b45 --- /dev/null +++ b/src/main/java/com/peanut/modules/common/entity/PayGoogleOrder.java @@ -0,0 +1,39 @@ +package com.peanut.modules.common.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +//google支付实体 +@Data +@TableName("pay_google_order") +public class PayGoogleOrder implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId + private Integer id; + //创建订单时间 + private Date createTime; + //用户Id + private Integer userId; + //订单Id + private Integer orderId; + //订单编号 + private String orderSn; + //订单类型 + private String orderType; + //google订单ID + private String googleOrderId; + //商品购买状态 + private Integer purchaseState; + //商品消耗状态 + private Integer consumptionState; + //执行扣款时间 + private Date googleOrderTime; + //支付回调数据 + private String callbackData; + +} diff --git a/src/main/java/com/peanut/modules/common/entity/UserEbookVip.java b/src/main/java/com/peanut/modules/common/entity/UserEbookVip.java new file mode 100644 index 0000000..2db4811 --- /dev/null +++ b/src/main/java/com/peanut/modules/common/entity/UserEbookVip.java @@ -0,0 +1,30 @@ +package com.peanut.modules.common.entity; + +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableLogic; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +//海外用户订阅表 +@Data +@TableName("user_ebook_vip") +public class UserEbookVip implements Serializable { + private static final long serialVersionUID = 1L; + + @TableId + private Integer id; + + private Integer userId; + + private Date startTime; + + private Date endTime; + + @TableLogic + private Integer delFlag; + + +} diff --git a/src/main/java/com/peanut/modules/common/service/UserEbookVipService.java b/src/main/java/com/peanut/modules/common/service/UserEbookVipService.java new file mode 100644 index 0000000..0a5eabb --- /dev/null +++ b/src/main/java/com/peanut/modules/common/service/UserEbookVipService.java @@ -0,0 +1,7 @@ +package com.peanut.modules.common.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.peanut.modules.common.entity.UserEbookVip; + +public interface UserEbookVipService extends IService { +} diff --git a/src/main/java/com/peanut/modules/common/service/impl/UserEbookVipServiceImpl.java b/src/main/java/com/peanut/modules/common/service/impl/UserEbookVipServiceImpl.java new file mode 100644 index 0000000..5361aee --- /dev/null +++ b/src/main/java/com/peanut/modules/common/service/impl/UserEbookVipServiceImpl.java @@ -0,0 +1,13 @@ +package com.peanut.modules.common.service.impl; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.peanut.modules.common.dao.UserEbookVipDao; +import com.peanut.modules.common.entity.UserEbookVip; +import com.peanut.modules.common.service.UserEbookVipService; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service("commonUserEbookVipService") +public class UserEbookVipServiceImpl extends ServiceImpl implements UserEbookVipService { +} diff --git a/src/main/java/com/peanut/modules/job/task/UserEbookVipTask.java b/src/main/java/com/peanut/modules/job/task/UserEbookVipTask.java new file mode 100644 index 0000000..caa15ed --- /dev/null +++ b/src/main/java/com/peanut/modules/job/task/UserEbookVipTask.java @@ -0,0 +1,22 @@ +package com.peanut.modules.job.task; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.peanut.modules.common.entity.UserEbookVip; +import com.peanut.modules.common.service.UserEbookVipService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import java.util.Date; + +@Component("userEbookVipTask") +public class UserEbookVipTask implements ITask{ + + @Autowired + private UserEbookVipService userEbookVipService; + + @Override + public void run(String params) { + userEbookVipService.remove( + new LambdaQueryWrapper().lt(UserEbookVip::getEndTime, new Date())); + } + +} diff --git a/src/main/java/com/peanut/modules/mq/Consumer/OrderCancelConsumer.java b/src/main/java/com/peanut/modules/mq/Consumer/OrderCancelConsumer.java index dccfa68..f2ca410 100644 --- a/src/main/java/com/peanut/modules/mq/Consumer/OrderCancelConsumer.java +++ b/src/main/java/com/peanut/modules/mq/Consumer/OrderCancelConsumer.java @@ -76,11 +76,10 @@ public class OrderCancelConsumer { if ("point".equals(buyOrder.getOrderType())){ BookBuyConfigEntity bookBuyConfigEntity = bookBuyConfigService.getById(buyOrder.getProductId()); MyUserEntity userEntity = userService.getById(buyOrder.getUserId()); - String money = bookBuyConfigEntity.getMoney(); //更新账户余额 - userService.rechargeHSPoint(userEntity,Integer.valueOf(money)); + userService.rechargeHSPoint(userEntity,bookBuyConfigEntity.getMoney().intValue()); //插入虚拟币消费记录 - transactionDetailsService.rechargeRecord(userEntity,money,payStripeOrder.getId(),"StripePay",buyOrder.getOrderSn()); + transactionDetailsService.rechargeRecord(userEntity,bookBuyConfigEntity.getMoney().toString(),payStripeOrder.getId(),"StripePay",buyOrder.getOrderSn()); //插入花生币充值记录 payPaymentOrderService.insertDetail(userEntity,bookBuyConfigEntity,payStripeOrder.getId().toString()); } diff --git a/src/main/java/com/peanut/modules/pay/IOSPay/controller/AppController.java b/src/main/java/com/peanut/modules/pay/IOSPay/controller/AppController.java index e8a14e2..71fde85 100644 --- a/src/main/java/com/peanut/modules/pay/IOSPay/controller/AppController.java +++ b/src/main/java/com/peanut/modules/pay/IOSPay/controller/AppController.java @@ -124,14 +124,13 @@ public class AppController { // 插入花生币 变动记录 BookBuyConfigEntity bookBuyConfigEntity = this.bookBuyConfigService.getById(Integer.valueOf(body)); MyUserEntity userEntity = userService.getById(Integer.valueOf(customerid)); - String realMoney = bookBuyConfigEntity.getMoney(); - userService.rechargeHSPoint(userEntity, Integer.valueOf(realMoney)); + userService.rechargeHSPoint(userEntity, bookBuyConfigEntity.getMoney().intValue()); //插入虚拟币消费记录 - transactionDetailsService.rechargeRecord(userEntity,realMoney,order.getId(),"苹果",order.getOrderid()); + transactionDetailsService.rechargeRecord(userEntity,bookBuyConfigEntity.getMoney().toString(),order.getId(),"苹果",order.getOrderid()); //插入花生币充值记录 payPaymentOrderService.insertDetail(userEntity,bookBuyConfigEntity,order.getTransactionId()); buyOrderService.updateOrderStatus(Integer.valueOf(customerid), dto.getOrderId(), "2"); - order.setMoney(Integer.valueOf(bookBuyConfigEntity.getRealMoney())); + order.setMoney(bookBuyConfigEntity.getRealMoney().intValue()); order.setUsername(userEntity.getName()); orderService.saveOrUpdate(order); orderService.update(); diff --git a/src/main/java/com/peanut/modules/pay/IOSPay/service/impl/OrderServiceImpl.java b/src/main/java/com/peanut/modules/pay/IOSPay/service/impl/OrderServiceImpl.java index 58320cf..b1ccbab 100644 --- a/src/main/java/com/peanut/modules/pay/IOSPay/service/impl/OrderServiceImpl.java +++ b/src/main/java/com/peanut/modules/pay/IOSPay/service/impl/OrderServiceImpl.java @@ -126,7 +126,7 @@ public class OrderServiceImpl extends ServiceImpl().eq("order_sn", order.getOrderid())); if (null != orderEntity) { diff --git a/src/main/java/com/peanut/modules/pay/alipay/service/impl/AliPayServiceImpl.java b/src/main/java/com/peanut/modules/pay/alipay/service/impl/AliPayServiceImpl.java index c24607a..43ef997 100644 --- a/src/main/java/com/peanut/modules/pay/alipay/service/impl/AliPayServiceImpl.java +++ b/src/main/java/com/peanut/modules/pay/alipay/service/impl/AliPayServiceImpl.java @@ -226,10 +226,9 @@ public class AliPayServiceImpl implements AliPayService { jfTransactionDetails.setRemark("充币送积分:"+bookBuyConfigEntity.getDescription()+",订单号:"+order.getOrderSn()); jfTransactionDetailsDao.insert(jfTransactionDetails); } - String realMoney = bookBuyConfigEntity.getRealMoney(); - userService.rechargeHSPoint(userEntity,Integer.valueOf(realMoney)); + userService.rechargeHSPoint(userEntity,bookBuyConfigEntity.getRealMoney().intValue()); //插入虚拟币消费记录 - transactionDetailsService.rechargeRecord(userEntity,realMoney,oldPayZfbOrderEntity.getId().intValue(),"支付宝",order.getOrderSn()); + transactionDetailsService.rechargeRecord(userEntity,bookBuyConfigEntity.getRealMoney().toString(),oldPayZfbOrderEntity.getId().intValue(),"支付宝",order.getOrderSn()); //插入花生币充值记录 payPaymentOrderService.insertDetail(userEntity,bookBuyConfigEntity,oldPayZfbOrderEntity.getId().toString()); buyOrderService.updateOrderStatus(Integer.valueOf(customerid),oldPayZfbOrderEntity.getRelevanceoid(),"2"); diff --git a/src/main/java/com/peanut/modules/pay/googlepay/GooglePayController.java b/src/main/java/com/peanut/modules/pay/googlepay/GooglePayController.java new file mode 100644 index 0000000..68293af --- /dev/null +++ b/src/main/java/com/peanut/modules/pay/googlepay/GooglePayController.java @@ -0,0 +1,223 @@ +package com.peanut.modules.pay.googlepay; + +import cn.hutool.core.codec.Base64; +import com.alibaba.fastjson.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import com.google.api.services.androidpublisher.AndroidPublisher; +import com.google.api.services.androidpublisher.model.ProductPurchase; +import com.google.api.services.androidpublisher.model.SubscriptionPurchase; +import com.peanut.common.utils.DateUtil; +import com.peanut.common.utils.DateUtils; +import com.peanut.common.utils.R; +import com.peanut.modules.book.service.UserEbookBuyService; +import com.peanut.modules.common.entity.BuyOrder; +import com.peanut.modules.common.entity.PayGoogleOrder; +import com.peanut.modules.common.entity.UserEbookVip; +import com.peanut.modules.common.entity.VipBuyConfigEntity; +import com.peanut.modules.common.service.BuyOrderService; +import com.peanut.modules.common.service.UserEbookVipService; +import com.peanut.modules.master.service.VipBuyConfigService; +import com.peanut.modules.pay.googlepay.config.DeveloperNotification; +import com.peanut.modules.pay.googlepay.config.GooglePayConfig; +import com.peanut.modules.pay.googlepay.service.PayGoogleOrderService; +import com.peanut.modules.sys.entity.SysDictDataEntity; +import com.peanut.modules.sys.service.impl.SysDictDataServiceImpl; +import lombok.extern.slf4j.Slf4j; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.util.Arrays; +import java.util.Date; +import java.util.Map; + +/** + * GooglePay支付 + */ +@RestController +@RequestMapping("/pay/googlepay") +@Slf4j +public class GooglePayController { + private Logger logger = LoggerFactory.getLogger(getClass()); + + @Autowired + private GooglePayConfig googlePayConfig; + @Autowired + private BuyOrderService buyOrderService; + @Autowired + private PayGoogleOrderService payGoogleOrderService; + @Autowired + private UserEbookBuyService userEbookBuyService; + @Autowired + private UserEbookVipService userEbookVipService; + @Autowired + private VipBuyConfigService vipBuyConfigService; + @Autowired + private SysDictDataServiceImpl sysDictDataService; + + //订单校验 + @RequestMapping(value = "/googleVerify") + public R verify(@RequestBody Map params) { + try { + String packageName = googlePayConfig.packageName(); + String productId = params.get("productId").toString(); + String purchaseToken = params.get("purchaseToken").toString(); + String orderSn = params.get("orderSn").toString(); + BuyOrder order = buyOrderService.getOne(new LambdaQueryWrapper().eq(BuyOrder::getOrderSn, orderSn)); + if (order != null&&!"3".equals(order.getOrderStatus())) { + AndroidPublisher authInstance = googlePayConfig.androidPublisher(); + PayGoogleOrder googleOrder = new PayGoogleOrder(); + googleOrder.setUserId(order.getUserId()); + googleOrder.setOrderId(order.getOrderId()); + googleOrder.setOrderSn(orderSn); + googleOrder.setOrderType(order.getOrderType()); + //校验谷歌消耗订单 + ProductPurchase purchase = authInstance.purchases().products().get(packageName, productId, purchaseToken).execute(); + //判断校验凭证是否和订单一致 + if(orderSn.equals(purchase.getObfuscatedExternalAccountId())){ + //{"acknowledgementState":0,"consumptionState":0,"developerPayload":"","kind":"androidpublisher#productPurchase", + // "obfuscatedExternalAccountId":"ordersn","orderId":"GPA.3383-6898-6457-86309","purchaseState":0, + // "purchaseTimeMillis":"1756193553018","purchaseType":0,"regionCode":"US"} + // 订单的购买状态。0. 已购买 1. 已取消 2. 待定 产品的消费状态。可能的值为: 0. 尚未消耗 1. 已消耗 + if (purchase.getPurchaseState() == 0 && purchase.getConsumptionState() == 1) { + googleOrder.setGoogleOrderId(purchase.getOrderId()); + googleOrder.setGoogleOrderTime(new Date(purchase.getPurchaseTimeMillis())); + payGoogleOrderService.save(googleOrder); + if ("abroadBook".equals(order.getOrderType())){ + userEbookBuyService.addBookForUser(order.getUserId(), Arrays.asList(order.getAbroadBookId())); + }else if ("abroadVip".equals(order.getOrderType())){ + UserEbookVip userEbookVip = new UserEbookVip(); + userEbookVip.setUserId(order.getUserId()); + Date date = new Date(); + userEbookVip.setStartTime(date); + SysDictDataEntity d = sysDictDataService.getById(order.getAbroadVipId()); + userEbookVip.setEndTime(DateUtils.addDateDays(date,Integer.parseInt(d.getRemark()))); + userEbookVipService.save(userEbookVip); + } + order.setOrderStatus("3"); + buyOrderService.updateById(order); + return R.ok(); + } + } +// SubscriptionPurchase purchaseSub = authInstance.purchases().subscriptions().get(packageName, productId, purchaseToken).execute(); +// //{"acknowledgementState":0,"consumptionState":0,"developerPayload":"","kind":"androidpublisher#productPurchase", +// // "obfuscatedExternalAccountId":"ordersn","orderId":"GPA.3383-6898-6457-86309","purchaseState":0, +// // "purchaseTimeMillis":"1756193553018","purchaseType":0,"regionCode":"US"} +// if (orderSn.equals(purchaseSub.getObfuscatedExternalAccountId())) { +// if(purchaseSub.getPaymentState() == 1) { +// googleOrder.setGoogleOrderId(purchaseSub.getOrderId()); +// googleOrder.setGoogleOrderTime(new Date()); +// payGoogleOrderService.save(googleOrder); +// UserEbookVip userEbookVip = new UserEbookVip(); +// userEbookVip.setUserId(order.getUserId()); +// userEbookVip.setStartTime(new Date(purchaseSub.getStartTimeMillis())); +// userEbookVip.setEndTime(new Date(purchaseSub.getExpiryTimeMillis())); +// userEbookVipService.save(userEbookVip); +// order.setOrderStatus("3"); +// buyOrderService.updateById(order); +// return R.ok(); +// } +// } + } + return R.error("Order Exception"); + } catch (Exception e) { + return R.error(e.toString()); + } + } + + @RequestMapping(value = "/callback") + public String googleNotify(@RequestBody(required = false) byte[] body) { + try { + String bodyStr = new String(body, "utf-8"); + JSONObject bodyJson = JSONObject.parseObject(bodyStr); + String dataJson = bodyJson.getJSONObject("message").getString("data"); + // base64解码data + String data = Base64.decodeStr(dataJson); + DeveloperNotification developerNotification = JSONObject.parseObject(data, DeveloperNotification.class); + AndroidPublisher authInstance = googlePayConfig.androidPublisher(); + //单次通知,校验订单时处理,不在回调中处理 + if (developerNotification.getOneTimeProductNotification() != null){ + ProductPurchase purchase = authInstance.purchases().products().get(googlePayConfig.packageName(), + developerNotification.getOneTimeProductNotification().getSku(), + developerNotification.getOneTimeProductNotification().getPurchaseToken()).execute(); + System.out.println("商品回调数据==="+developerNotification); + System.out.println("商品数据==="+purchase); + } + //订阅通知 + if (developerNotification.getSubscriptionNotification() != null){ + System.out.println("订阅回调数据==="+developerNotification); + SubscriptionPurchase purchaseSub = authInstance.purchases().subscriptions().get( + googlePayConfig.packageName(), + developerNotification.getSubscriptionNotification().getSubscriptionId(), + developerNotification.getSubscriptionNotification().getPurchaseToken()).execute(); + System.out.println("订阅数据==="+purchaseSub); + int notificationType = developerNotification.getSubscriptionNotification().getNotificationType(); + //判断通知类型https://developer.android.google.cn/google/play/billing/lifecycle/subscriptions?hl=el +// if (1 == notificationType)//从保留状态恢复了订阅 + if (2 == notificationType) {//续订了订阅 + //根据现在请求谷歌的googleOrderId获取续订包的订单,获取用户跟productId + //续订的谷歌订单是有规则的,比如你第一次购买产生的订单是GPA.123-456-789,那第一次续订的产生的订单号是GPA.123-456-789..0,第二次GPA.123-456-789..1,依次类推。 + //续订这里还有一个坑,当订阅包降级购买的时候,谷歌并不是通知你购买了新订阅包而是续订,比如你购买的高级订阅包是GPA.123-456-789,当你切换低级的订阅包的时候订单号为GPA.111-222-333..0,你会发现订单号变了,这时候就难办了,拿不到之前用户的信息(谷歌返回的订单参数是没有项目里面用户信息的),经过联调发现,他们两个订单的linkedPurchaseToken是一样的,可以参考上图中参数的介绍 + //当降级和自动续订的时候都会走这个通知,所以里面有两个逻辑,需要自己去判断,这两者的不同上面都写的很清楚了。 + if(purchaseSub.getPaymentState() == 1) { + BuyOrder oldOrder = buyOrderService.getOne(new LambdaQueryWrapper() + .eq(BuyOrder::getOrderSn, purchaseSub.getObfuscatedExternalAccountId())); + BuyOrder buyOrder = new BuyOrder(); + buyOrder.setOrderSn(IdWorker.getTimeId().substring(0, 32)); + buyOrder.setUserId(oldOrder.getUserId()); + buyOrder.setCome(3); + buyOrder.setPaymentMethod("5"); + buyOrder.setOrderStatus("3"); + buyOrder.setOrderType(oldOrder.getOrderType()); + buyOrder.setOrderMoney(oldOrder.getOrderMoney()); + buyOrder.setRealMoney(oldOrder.getRealMoney()); + buyOrder.setCreateTime(new Date()); + buyOrder.setRemark("renew"+oldOrder.getRemark()); + buyOrder.setAbroadBookId(oldOrder.getAbroadBookId()); + buyOrder.setVipBuyConfigId(oldOrder.getVipBuyConfigId()); + buyOrderService.save(buyOrder); + PayGoogleOrder googleOrder = new PayGoogleOrder(); + googleOrder.setUserId(buyOrder.getUserId()); + googleOrder.setOrderId(buyOrder.getOrderId()); + googleOrder.setOrderSn(buyOrder.getOrderSn()); + googleOrder.setOrderType(buyOrder.getOrderType()); + googleOrder.setGoogleOrderId(purchaseSub.getOrderId()); + googleOrder.setGoogleOrderTime(new Date()); + payGoogleOrderService.save(googleOrder); + UserEbookVip userEbookVip = userEbookVipService.getOne(new LambdaQueryWrapper() + .eq(UserEbookVip::getUserId,buyOrder.getUserId())); + userEbookVip.setStartTime(new Date(purchaseSub.getStartTimeMillis())); + userEbookVip.setEndTime(new Date(purchaseSub.getExpiryTimeMillis())); + userEbookVipService.updateById(userEbookVip); + } + } +// if (3 == notificationType)//取消了订阅 +// if (4 == notificationType)//新购买的订阅 +// //校验订单时处理,不在回调中处理 +// if (5 == notificationType)//订阅已进入帐号保留状态(如果已启用)。 +// if (6 == notificationType)//订阅已进入宽限期(如果已启用)。 +// if (7 == notificationType)//用户已通过 Play > 帐号 > 订阅恢复了订阅。订阅已取消,但在用户恢复时尚未到期。如需了解详情,请参阅恢复。 +// if (8 == notificationType)//用户已成功确认订阅价格变动。 +// if (9 == notificationType)//订阅的续订时间点已延期。 +// if (10 == notificationType)//订阅暂停 +// if (11 == notificationType)//订阅暂停计划已更改。 + if (12 == notificationType){//用户在到期时间之前已撤消订阅。 + BuyOrder oldOrder = buyOrderService.getOne(new LambdaQueryWrapper() + .eq(BuyOrder::getOrderSn, purchaseSub.getObfuscatedExternalAccountId())); + userEbookVipService.remove(new LambdaQueryWrapper() + .eq(UserEbookVip::getUserId,oldOrder.getUserId())); + } +// if (13 == notificationType)//订阅已到期。 + } + } catch (Exception e) { + e.printStackTrace(); + } + return null; + } + + + +} diff --git a/src/main/java/com/peanut/modules/pay/googlepay/config/DeveloperNotification.java b/src/main/java/com/peanut/modules/pay/googlepay/config/DeveloperNotification.java new file mode 100644 index 0000000..43beebd --- /dev/null +++ b/src/main/java/com/peanut/modules/pay/googlepay/config/DeveloperNotification.java @@ -0,0 +1,37 @@ +package com.peanut.modules.pay.googlepay.config; + + +import com.peanut.modules.pay.googlepay.service.SubscriptionNotification; +import lombok.Data; + +import java.io.Serializable; + +@Data +public class DeveloperNotification implements Serializable { + + /** + * 此通知的版本。最初,此值为“1.0”。此版本与其他版本字段不同。 + */ + private String version; + + /** + * 与此通知相关的应用的软件包名称(例如“com.some.thing”)。 + */ + private String packageName; + + /** + * 事件发生的时间戳,以从公元纪年开始计算的毫秒数表示。 + */ + private long eventTimeMillis; + + /** + * 如果此字段存在,则此通知与订阅相关,并且此字段包含与订阅相关的其他信息。请注意,此字段与 testNotification 和 oneTimeProductNotification 互斥。 + */ + private SubscriptionNotification subscriptionNotification; + + /** + * 如果此字段存在,则此通知与一次性购买相关,并且此字段包含与购买交易相关的其他信息。请注意,此字段与 testNotification 和 subscriptionProductNotification 互斥。 + */ + private OneTimeProductNotification oneTimeProductNotification; + +} diff --git a/src/main/java/com/peanut/modules/pay/googlepay/config/GooglePayConfig.java b/src/main/java/com/peanut/modules/pay/googlepay/config/GooglePayConfig.java new file mode 100644 index 0000000..08ed0a7 --- /dev/null +++ b/src/main/java/com/peanut/modules/pay/googlepay/config/GooglePayConfig.java @@ -0,0 +1,61 @@ +package com.peanut.modules.pay.googlepay.config; + +import java.util.ArrayList; +import java.util.List; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.io.DefaultResourceLoader; +import org.springframework.core.io.Resource; +import org.springframework.core.io.ResourceLoader; +import com.google.api.client.googleapis.auth.oauth2.GoogleCredential; +import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport; +import com.google.api.client.http.HttpTransport; +import com.google.api.client.json.jackson2.JacksonFactory; +import com.google.api.services.androidpublisher.AndroidPublisher; +import com.google.api.services.androidpublisher.AndroidPublisherScopes; +import lombok.extern.slf4j.Slf4j; + +//谷歌pay 配置 +@Configuration +@Slf4j +public class GooglePayConfig { + + @Value("${googlepay.packageName}") + private String packageName; + + @Bean + public AndroidPublisher androidPublisher() { + log.info("---------------------开始初始化Google服务,包名:{}---------------------", packageName); + System.out.println("---------------------开始初始化Google服务,包名:{}---------------------"+packageName); + AndroidPublisher androidPublisher; + try { + // 1.使用服务帐户Json文件获取Google凭据 + List scopes = new ArrayList<>(); + scopes.add(AndroidPublisherScopes.ANDROIDPUBLISHER); + ResourceLoader resourceLoader = new DefaultResourceLoader(); + Resource resource = resourceLoader.getResource("/googlepay/amazing-reading-c09fbcab23d9.json"); + GoogleCredential credential = GoogleCredential.fromStream(resource.getInputStream()).createScoped(scopes); + + // 2.使用谷歌凭据和收据从谷歌获取购买信息 + // 代理配置 + // 参考:https://juejin.cn/post/7374308419073589257?searchId=2024121315513006E2F4BC455000133E11#heading-8 + HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport(); + JacksonFactory jsonFactory = new JacksonFactory(); + + androidPublisher = new AndroidPublisher.Builder(httpTransport, jsonFactory, credential) + .setApplicationName(packageName).build(); + log.info("---------------------初始化Google服务成功---------------------success"); + System.out.println("---------------------初始化Google服务成功---------------------success"); + } catch (Exception ex) { + log.error("---------------------初始化Google服务失败:", ex); + System.out.println("---------------------初始化Google服务失败"+ex); + throw new RuntimeException(ex); + } + return androidPublisher; + } + + public String packageName() { + return packageName; + } +} diff --git a/src/main/java/com/peanut/modules/pay/googlepay/config/OneTimeProductNotification.java b/src/main/java/com/peanut/modules/pay/googlepay/config/OneTimeProductNotification.java new file mode 100644 index 0000000..17f47f8 --- /dev/null +++ b/src/main/java/com/peanut/modules/pay/googlepay/config/OneTimeProductNotification.java @@ -0,0 +1,34 @@ +package com.peanut.modules.pay.googlepay.config; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 谷歌开发者回调单次通知信息 + */ +@Data +public class OneTimeProductNotification implements Serializable { + + /** + * 通知的版本。最初,此值为“1.0”。此版本与其他版本字段不同。 + */ + private String version; + + /** + * 通知的类型。它可以具有以下值: + * (1) ONE_TIME_PRODUCT_PURCHASED - 用户成功购买了一次性商品。 + * (2) ONE_TIME_PRODUCT_CANCELED - 用户已取消待处理的一次性商品购买交易。 + */ + private int notificationType; + + /** + * 购买订阅时向用户设备提供的令牌。 + */ + private String purchaseToken; + + /** + * 购买的一次性商品的商品 ID(例如“sword_001”)。 + */ + private String sku; +} diff --git a/src/main/java/com/peanut/modules/pay/googlepay/service/PayGoogleOrderService.java b/src/main/java/com/peanut/modules/pay/googlepay/service/PayGoogleOrderService.java new file mode 100644 index 0000000..7516246 --- /dev/null +++ b/src/main/java/com/peanut/modules/pay/googlepay/service/PayGoogleOrderService.java @@ -0,0 +1,7 @@ +package com.peanut.modules.pay.googlepay.service; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.peanut.modules.common.entity.PayGoogleOrder; + +public interface PayGoogleOrderService extends IService { +} diff --git a/src/main/java/com/peanut/modules/pay/googlepay/service/PayGoogleOrderServiceImpl.java b/src/main/java/com/peanut/modules/pay/googlepay/service/PayGoogleOrderServiceImpl.java new file mode 100644 index 0000000..e8d0bd0 --- /dev/null +++ b/src/main/java/com/peanut/modules/pay/googlepay/service/PayGoogleOrderServiceImpl.java @@ -0,0 +1,13 @@ +package com.peanut.modules.pay.googlepay.service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.peanut.modules.common.dao.PayGoogleOrderDao; +import com.peanut.modules.common.entity.PayGoogleOrder; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Service; + +@Slf4j +@Service("payGoogleOrderService") +public class PayGoogleOrderServiceImpl extends ServiceImpl implements PayGoogleOrderService { +} + diff --git a/src/main/java/com/peanut/modules/pay/googlepay/service/SubscriptionNotification.java b/src/main/java/com/peanut/modules/pay/googlepay/service/SubscriptionNotification.java new file mode 100644 index 0000000..e390f10 --- /dev/null +++ b/src/main/java/com/peanut/modules/pay/googlepay/service/SubscriptionNotification.java @@ -0,0 +1,46 @@ +package com.peanut.modules.pay.googlepay.service; + +import lombok.Data; + +import java.io.Serializable; + +/** + * 谷歌开发者回调订阅通知信息 + */ +@Data +public class SubscriptionNotification implements Serializable { + + /** + * 通知的版本。最初,此值为“1.0”。此版本与其他版本字段不同。 + */ + private String version; + + /** + * 订阅的 notificationType 可以具有以下值: + * (1) SUBSCRIPTION_RECOVERED - 从帐号保留状态恢复了订阅。 + * (2) SUBSCRIPTION_RENEWED - 续订了处于活动状态的订阅。 + * (3) SUBSCRIPTION_CANCELED - 自愿或非自愿地取消了订阅。如果是自愿取消,在用户取消时发送。 + * (4) SUBSCRIPTION_PURCHASED - 购买了新的订阅。 + * (5) SUBSCRIPTION_ON_HOLD - 订阅已进入帐号保留状态(如果已启用)。 + * (6) SUBSCRIPTION_IN_GRACE_PERIOD - 订阅已进入宽限期(如果已启用)。 + * (7) SUBSCRIPTION_RESTARTED - 用户已通过 Play > 帐号 > 订阅恢复了订阅。订阅已取消,但在用户恢复时尚未到期。如需了解详情,请参阅恢复。 + * (8) SUBSCRIPTION_PRICE_CHANGE_CONFIRMED - 用户已成功确认订阅价格变动。 + * (9) SUBSCRIPTION_DEFERRED - 订阅的续订时间点已延期。 + * (10) SUBSCRIPTION_PAUSED - 订阅已暂停。 + * (11) SUBSCRIPTION_PAUSE_SCHEDULE_CHANGED - 订阅暂停计划已更改。 + * (12) SUBSCRIPTION_REVOKED - 用户在到期时间之前已撤消订阅。 + * (13) SUBSCRIPTION_EXPIRED - 订阅已到期。 + */ + private int notificationType; + + /** + * 购买订阅时向用户设备提供的令牌。 + */ + private String purchaseToken; + + /** + * 所购买订阅的商品 ID(例如“monthly001”)。 + */ + private String subscriptionId; +} + diff --git a/src/main/java/com/peanut/modules/pay/paypal/controller/PaypalController.java b/src/main/java/com/peanut/modules/pay/paypal/controller/PaypalController.java index 9041883..27b3a55 100644 --- a/src/main/java/com/peanut/modules/pay/paypal/controller/PaypalController.java +++ b/src/main/java/com/peanut/modules/pay/paypal/controller/PaypalController.java @@ -110,11 +110,10 @@ public class PaypalController { if ("point".equals(buyOrder.getOrderType())){ BookBuyConfigEntity bookBuyConfigEntity = bookBuyConfigService.getById(buyOrder.getProductId()); MyUserEntity userEntity = userService.getById(buyOrder.getUserId()); - String money = bookBuyConfigEntity.getMoney(); //更新账户余额 - userService.rechargeHSPoint(userEntity,Integer.valueOf(money)); + userService.rechargeHSPoint(userEntity,bookBuyConfigEntity.getMoney().intValue()); //插入虚拟币消费记录 - transactionDetailsService.rechargeRecord(userEntity,money,payPaypalOrder.getId(),"PayPal",buyOrder.getOrderSn()); + transactionDetailsService.rechargeRecord(userEntity,bookBuyConfigEntity.getMoney().toString(),payPaypalOrder.getId(),"PayPal",buyOrder.getOrderSn()); //插入花生币充值记录 payPaymentOrderService.insertDetail(userEntity,bookBuyConfigEntity,payPaypalOrder.getId().toString()); } diff --git a/src/main/java/com/peanut/modules/pay/stripe/StripeController.java b/src/main/java/com/peanut/modules/pay/stripe/StripeController.java index d30af6c..6089ab4 100644 --- a/src/main/java/com/peanut/modules/pay/stripe/StripeController.java +++ b/src/main/java/com/peanut/modules/pay/stripe/StripeController.java @@ -121,11 +121,10 @@ public class StripeController { if ("point".equals(buyOrder.getOrderType())){ BookBuyConfigEntity bookBuyConfigEntity = bookBuyConfigService.getById(buyOrder.getProductId()); MyUserEntity userEntity = userService.getById(buyOrder.getUserId()); - String money = bookBuyConfigEntity.getMoney(); //更新账户余额 - userService.rechargeHSPoint(userEntity,Integer.valueOf(money)); + userService.rechargeHSPoint(userEntity,bookBuyConfigEntity.getMoney().intValue()); //插入虚拟币消费记录 - transactionDetailsService.rechargeRecord(userEntity,money,payStripeOrder.getId(),"Stripe",buyOrder.getOrderSn()); + transactionDetailsService.rechargeRecord(userEntity,bookBuyConfigEntity.getMoney().toString(),payStripeOrder.getId(),"Stripe",buyOrder.getOrderSn()); //插入花生币充值记录 payPaymentOrderService.insertDetail(userEntity,bookBuyConfigEntity,payStripeOrder.getId().toString()); } diff --git a/src/main/java/com/peanut/modules/pay/weChatPay/service/impl/WxpayServiceImpl.java b/src/main/java/com/peanut/modules/pay/weChatPay/service/impl/WxpayServiceImpl.java index 96930d6..a128b1f 100644 --- a/src/main/java/com/peanut/modules/pay/weChatPay/service/impl/WxpayServiceImpl.java +++ b/src/main/java/com/peanut/modules/pay/weChatPay/service/impl/WxpayServiceImpl.java @@ -297,10 +297,9 @@ public class WxpayServiceImpl extends ServiceImpl params){ + SysDictDataEntity sysDictData = sysDictDataService.getById(params.get("id").toString()); + return R.ok().put("sysDictData", sysDictData); + } + + /** + * 信息 + */ + @RequestMapping("/getData") + public R getData(@RequestBody Map params){ + List sysDictDatas = sysDictDataService.list(new LambdaQueryWrapper() + .eq(SysDictDataEntity::getDictLabel,params.get("dictLabel")).orderByAsc(SysDictDataEntity::getSort)); + return R.ok().put("sysDictDatas", sysDictDatas); + } /** * 信息 diff --git a/src/main/java/com/peanut/modules/sys/dao/SysDictDataDao.java b/src/main/java/com/peanut/modules/sys/dao/SysDictDataDao.java index dd2b25f..65d2c7e 100644 --- a/src/main/java/com/peanut/modules/sys/dao/SysDictDataDao.java +++ b/src/main/java/com/peanut/modules/sys/dao/SysDictDataDao.java @@ -1,6 +1,6 @@ -package com.peanut.modules.book.dao; +package com.peanut.modules.sys.dao; -import com.peanut.modules.book.entity.SysDictDataEntity; +import com.peanut.modules.sys.entity.SysDictDataEntity; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Mapper; diff --git a/src/main/java/com/peanut/modules/sys/entity/SysDictDataEntity.java b/src/main/java/com/peanut/modules/sys/entity/SysDictDataEntity.java index 05995be..b308bce 100644 --- a/src/main/java/com/peanut/modules/sys/entity/SysDictDataEntity.java +++ b/src/main/java/com/peanut/modules/sys/entity/SysDictDataEntity.java @@ -1,4 +1,4 @@ -package com.peanut.modules.book.entity; +package com.peanut.modules.sys.entity; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/src/main/java/com/peanut/modules/sys/service/SysDictDataService.java b/src/main/java/com/peanut/modules/sys/service/SysDictDataService.java index 15c49b5..29d7ea5 100644 --- a/src/main/java/com/peanut/modules/sys/service/SysDictDataService.java +++ b/src/main/java/com/peanut/modules/sys/service/SysDictDataService.java @@ -2,7 +2,7 @@ package com.peanut.modules.sys.service; import com.baomidou.mybatisplus.extension.service.IService; import com.peanut.common.utils.PageUtils; -import com.peanut.modules.book.entity.SysDictDataEntity; +import com.peanut.modules.sys.entity.SysDictDataEntity; import java.util.Map; diff --git a/src/main/java/com/peanut/modules/sys/service/impl/SysDictDataServiceImpl.java b/src/main/java/com/peanut/modules/sys/service/impl/SysDictDataServiceImpl.java index e85e090..584308a 100644 --- a/src/main/java/com/peanut/modules/sys/service/impl/SysDictDataServiceImpl.java +++ b/src/main/java/com/peanut/modules/sys/service/impl/SysDictDataServiceImpl.java @@ -10,8 +10,8 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.peanut.common.utils.PageUtils; import com.peanut.common.utils.Query; -import com.peanut.modules.book.dao.SysDictDataDao; -import com.peanut.modules.book.entity.SysDictDataEntity; +import com.peanut.modules.sys.dao.SysDictDataDao; +import com.peanut.modules.sys.entity.SysDictDataEntity; @Slf4j @Service("sysDictDataService") diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 129ae1b..5171c11 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -97,3 +97,7 @@ sms: account: 921689 pswd: 9de2a579 content: Tianjin Zhongmiao Gate Technology:Your verification code is:XXXXXX. + + +googlepay: + packageName: io.reading.test \ No newline at end of file diff --git a/src/main/resources/googlepay/amazing-reading-c09fbcab23d9.json b/src/main/resources/googlepay/amazing-reading-c09fbcab23d9.json new file mode 100644 index 0000000..55bc221 --- /dev/null +++ b/src/main/resources/googlepay/amazing-reading-c09fbcab23d9.json @@ -0,0 +1,13 @@ +{ + "type": "service_account", + "project_id": "amazing-reading", + "private_key_id": "c09fbcab23d9c4b37451efc25c2b1ee8a1e57049", + "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDjQrNzjt61+Osm\nzmBgxqOMvQBiZjUieT9Lltcm0g2f+zXRLhsfkuP3u0Tnmzbr4EQKkjofcQNNHzjz\n7d2rfmNh2aaWMB8fUN7U0yj2QJw6Htpl6f+2SVvM6r9JAkEFCAsgGp6E91kIhKl4\nooIaf4ImtghoOsAVH1gtlwp6fH5bJNRdeikJM8XTjPIBhmCLnfKf6E2CJL1ledVf\n++fMNLOjgJN8n7SdBWpGR8ZtjBFynopADKa9Umaka03YFnHpEyBffD1rbFK5yIES\nhJy2JaMLIdEzJHdiJ8/7wl4S+7eD4ENA/tVol9ug3EhYR62OIc3jEJLxRJza0YYO\nZCUKpJwpAgMBAAECggEAAUXDO6/g3EvGMil3dHj7shnL0wE6AUvyby09pz2Z7rcS\na0BAqUU0nKWtr/xz1AZcV76q77hZB1lFqEKTUSR5x3vy5qq+YnCvF05XPUTlIegJ\nrWIOAghTxDqUadVG7v8+NiIhKr5c0XDtlLcqO4v3KMdnFdzk7KlahPBCrcuvcieN\nHM0asI5oWZxl6pLr9fTUD3BakX3GEAEzH0HttHjWT81B7yhJSyWmJ9z4PyHbx/sO\nEjjAcHrOR+feH4SGKDOrTouGE9mIl/wiHM45DsiNlEWwmjuMRLSc2StJAnQfA0S6\nvAme76Kl0djbyQjln2Lg/C/ZBDlwrdbxoJ1mMntY9QKBgQD+bqPqj15qf7HwVe3i\nmPRLP0yEl//LZwMtrO3hI/GG+deejhSkyib94cMPYdqFvo7TJW7b95toEwKDY05A\nweo/WWDxuAXVvylzO4fZqRp12iHgCCBSesAEJ3mPXXcpCOjuOXa1UsCom/P6Vk3d\nWTjwgI53kIeVzcnmSuP2l400vQKBgQDkqTK7/AuWQ1z335TUiYtrpPwmgNCe7tu4\ni/pYMrwQCc7P6vneEL9eG6E3PHQKodA+8i22YUlWOGjYcEtYr0qCDG26aTOAh2f/\nwXnhRK0LYRjYO4eLWfJ8B52RU6LG3Wj91yxbgL3XqPjOPn3NUXxmi4KWga5ex7sI\nsF9ZqQA53QKBgQDfmmS8M5uKhQbgbORPjJTFvK+Gp/7Jx5Jnhd7ZSjltogz472z9\nFhwGa25+CkV93Oawcelnr8gIQwymY5PWHZW8btRgGpYmL4ZCG0Nc6tyyTi4PMZUW\nZ4JxJDAU6tNaYNY05pOI710Z0VUt4MM1kMAVvSV3trEx2lVh6tdFVBNpEQKBgQCl\n5KddQRg69TZu0zQMGpofB7y0RoKUvCCGvG9tK6nLTQJRUF3loWrlYNBO3bomuIz4\nDgXiKqTlO9m9JYNUnSBGR7QYKRjnZ9Wo9Ppy17tf5Rr8Tfwhuqk1GOVVOUOAWcRB\nXand3QJeg0W3hBkLK9JAJ3kfrogOVYO5YxRaXUU/tQKBgQCcCc4VKwRYBGcNkxtN\ncJ1aI5DhqJuTanyaBQ2jsf/X+OtBzc1WlC+2FI1YdAbZCI5Y2q0tXmvPT3/oCMgM\nZt4kkiEBRySk8mcqKBr2IY3lzQ5uh05OiTxkuQB1zWGvUILklwl+Kgo6FjjHbLBC\nXbMPWOuUjHi9PNDO6rvpY8UWCQ==\n-----END PRIVATE KEY-----\n", + "client_email": "amazingreading@amazing-reading.iam.gserviceaccount.com", + "client_id": "118137257029599724068", + "auth_uri": "https://accounts.google.com/o/oauth2/auth", + "token_uri": "https://oauth2.googleapis.com/token", + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", + "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/amazingreading%40amazing-reading.iam.gserviceaccount.com", + "universe_domain": "googleapis.com" +} diff --git a/src/main/resources/mapper/sys/SysDictDataDao.xml b/src/main/resources/mapper/sys/SysDictDataDao.xml index 9fd4e5e..a957080 100644 --- a/src/main/resources/mapper/sys/SysDictDataDao.xml +++ b/src/main/resources/mapper/sys/SysDictDataDao.xml @@ -1,10 +1,10 @@ - + - +