8 Commits 4493a1ec47 ... 499fb995a7

Auteur SHA1 Message Date
  qzy 499fb995a7 Merge remote-tracking branch 'origin/feature/asyncOrder' into feature/asyncOrder il y a 2 semaines
  qzy 6e70ef7625 Merge branch 'feature/asyncOrder' into feature/payTemp il y a 2 semaines
  qzy 60fcdff55b 服务点充值,扣除 il y a 2 semaines
  qzy d2f9afb235 依赖管理 il y a 3 semaines
  panlijun 11ccd85137 Merge branch 'feature/wxPay' of http://git.aseanbusiness.cn/qzyReal/market-server into feature/wxPay il y a 3 semaines
  panlijun 7c94c83ec5 增加了微信支付接口处理。 il y a 3 semaines
  qzy 0eec3f1662 Merge remote-tracking branch 'origin/feature/wxPay' into feature/payTemp il y a 1 mois
  panlijun 4479683958 1、边民信息增加服务点数; il y a 2 mois
43 fichiers modifiés avec 2912 ajouts et 162 suppressions
  1. 0 5
      sp-core/sp-base/pom.xml
  2. 3 2
      sp-core/sp-base/src/main/java/com/pj/project4sp/spcfg/SpCfgService.java
  3. 4 0
      sp-core/sp-base/src/main/java/com/pj/project4sp/spcfg/SpCfgUtil.java
  4. 72 72
      sp-core/sp-base/src/main/java/com/pj/utils/cache/RedisUtil.java
  5. 10 0
      sp-service/level-one-server/pom.xml
  6. 4 0
      sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrder.java
  7. 29 5
      sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderAppController.java
  8. 1 0
      sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderMapper.xml
  9. 42 9
      sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderService.java
  10. 74 67
      sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeople.java
  11. 4 0
      sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeopleMapper.java
  12. 7 2
      sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeopleMapper.xml
  13. 4 0
      sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeopleService.java
  14. 368 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletAppController.java
  15. 138 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecord.java
  16. 58 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordController.java
  17. 39 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordMapper.java
  18. 79 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordMapper.xml
  19. 70 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordService.java
  20. 63 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/WxPayConfiguration.java
  21. 53 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/WxPayProperties.java
  22. 103 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/app/AppServiceExample.java
  23. 93 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/app/AppServiceExtensionExample.java
  24. 47 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/vo/NotifyBO.java
  25. 42 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/vo/WalletRecordAppVo.java
  26. 12 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/vo/WalletRecordVo.java
  27. 118 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/EntPayController.java
  28. 121 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdown.java
  29. 87 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownController.java
  30. 29 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownMapper.java
  31. 72 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownMapper.xml
  32. 55 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownService.java
  33. 17 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/vo/WalletTopdownVo.java
  34. 143 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopup.java
  35. 73 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupController.java
  36. 51 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupMapper.java
  37. 70 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupMapper.xml
  38. 196 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupService.java
  39. 51 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/WalletTopupAppController.java
  40. 352 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/WxPayController.java
  41. 33 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/task/QueryPayTask.java
  42. 19 0
      sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/vo/ValletTopupVo.java
  43. 6 0
      sp-service/sp-admin/pom.xml

+ 0 - 5
sp-core/sp-base/pom.xml

@@ -41,11 +41,6 @@
             <version>2.1.0</version>
         </dependency>
 
-        <dependency>
-            <groupId>com.arcsoft.face</groupId>
-            <artifactId>arcsoft-sdk-face</artifactId>
-            <version>3.0.0.0</version>
-        </dependency>
         <!--人脸识别 阿里云 新版-->
         <dependency>
             <groupId>com.aliyun</groupId>

+ 3 - 2
sp-core/sp-base/src/main/java/com/pj/project4sp/spcfg/SpCfgService.java

@@ -18,14 +18,15 @@ public class SpCfgService {
 	/** 获得cfg_value 根据cfgName */
 	@Cacheable(value="sp_cfg_", key="#cfgName")	
 	public String getCfgValue(String cfgName){
-		return SP.publicMapper.getColumnByWhere("sp_cfg", "cfg_value", "cfg_name", cfgName);
+		return SP.publicMapper.getColumnByWhere("`sp-admin`.sp_cfg", "cfg_value", "cfg_name", cfgName);
 	}
 	
 	
 	/** 修改cfg_value 根据cfgName */
 	@CacheEvict(value="sp_cfg_", key="#cfgName")
 	public int updateCfgValue(String cfgName, String cfgValue){
-		return SP.publicMapper.updateColumnBy("sp_cfg", "cfg_value", cfgValue, "cfg_name", cfgName);
+		int	num=SpCfgUtil.getTradeNum();
+		return SP.publicMapper.updateColumnBy("`sp-admin`.sp_cfg", "cfg_value", cfgValue, "cfg_name", cfgName);
 	}
 	
 	

+ 4 - 0
sp-core/sp-base/src/main/java/com/pj/project4sp/spcfg/SpCfgUtil.java

@@ -79,6 +79,10 @@ public class SpCfgUtil {
 	public static String appName() {
 		return SpCfgUtil.getAppCfg("appName", "");
 	}
+	public static Integer getTradeNum() {
+		String num= SpCfgUtil.getAppCfg("tradeNum", "1");
+		return Integer.parseInt(num);
+	}
 	/** 获取配置信息:版本号  */
 	public static String appVersionNo() {
 		return SpCfgUtil.getAppCfg("appVersionNo", "");

+ 72 - 72
sp-core/sp-base/src/main/java/com/pj/utils/cache/RedisUtil.java

@@ -10,110 +10,110 @@ import org.springframework.stereotype.Component;
 
 /**
  * Redis工具类
- * @author kongyongshun
  *
+ * @author kongyongshun
  */
 @Component
 public class RedisUtil {
 
 
-	public static long ttl = 24* 7;	//默认超时时间,单位周,此为一周
-
-
-	/**
-	 * 对象专用
-	 */
-	public static RedisTemplate<String, Object> redisTemplate;
-	@Autowired
-	@SuppressWarnings({ "rawtypes", "unchecked" })
-	public void setRedisTemplate(RedisTemplate redisTemplate) {
-		RedisUtil.redisTemplate = redisTemplate;
-	}
+    public static long ttl = 24 * 7;    //默认超时时间,单位周,此为一周
 
-	/**
-	 * string专用
-	 */
-	static StringRedisTemplate stringRedisTemplate;
-	@Autowired
-	public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplates) {
-		RedisUtil.stringRedisTemplate = stringRedisTemplates;
-	}
 
+    /**
+     * 对象专用
+     */
+    public static RedisTemplate<String, Object> redisTemplate;
 
+    @Autowired
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public void setRedisTemplate(RedisTemplate redisTemplate) {
+        RedisUtil.redisTemplate = redisTemplate;
+    }
 
-	/* * * * * * * * * * * * * * * * String操作 * * * * * * * * * * * * * * * * * * * * * * * * */
+    /**
+     * string专用
+     */
+    static StringRedisTemplate stringRedisTemplate;
 
+    @Autowired
+    public void setStringRedisTemplate(StringRedisTemplate stringRedisTemplates) {
+        RedisUtil.stringRedisTemplate = stringRedisTemplates;
+    }
 
-	// 默认7*24小时
-	public static void set(String key, String value) {
-		stringRedisTemplate.opsForValue().set(key, value, ttl, TimeUnit.HOURS);
-	}
-	public static void setBySECONDS(String key, String value,int time) {
-		stringRedisTemplate.opsForValue().set(key, value, ttl, TimeUnit.MINUTES);
-	}
 
-	// 写入,并设置时长,单位 Hours
-	public static void setByHour(String key, String value, int timeout) {
-		stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.HOURS);
-	}
-	
-	// 写入,并设置时长,单位 分钟 MINUTES
-	public static void setByMINUTES(String key, String value, int timeout) {
-		stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.MINUTES);
-	}
 
-	// 读取
-	public static String get(String key) {
-		return stringRedisTemplate.opsForValue().get(key);
-	}
+    /* * * * * * * * * * * * * * * * String操作 * * * * * * * * * * * * * * * * * * * * * * * * */
 
 
-	// 删除
-	public static void del(String key) {
-		stringRedisTemplate.delete(key);
-	}
+    // 默认7*24小时
+    public static void set(String key, String value) {
+        stringRedisTemplate.opsForValue().set(key, value, ttl, TimeUnit.HOURS);
+    }
 
+    public static void setBySECONDS(String key, String value, int time) {
+        stringRedisTemplate.opsForValue().set(key, value, ttl, TimeUnit.MINUTES);
+    }
 
-	/* * * * * * * * * * * * * * * * List集合操作 * * * * * * * * * * * * * * * * * * * * * * * * */
+    // 写入,并设置时长,单位 Hours
+    public static void setByHour(String key, String value, int timeout) {
+        stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.HOURS);
+    }
 
-	// 查询
-	public static List<Object> forListGet(String key){
-		return redisTemplate.opsForList().range(key, 0, -1);
-	}
+    // 写入,并设置时长,单位 分钟 MINUTES
+    public static void setByMINUTES(String key, String value, int timeout) {
+        stringRedisTemplate.opsForValue().set(key, value, timeout, TimeUnit.MINUTES);
+    }
 
-	// 追加键值
-	public static void forListAdd(String key, Object... args){
-		redisTemplate.opsForList().rightPushAll(key,  args);
-	}
+    // 读取
+    public static String get(String key) {
+        return stringRedisTemplate.opsForValue().get(key);
+    }
 
-	// 移除所有键值
-	public static void forListRemove(String key){
-		List<Object> list = forListGet(key);
-		for (int i = 0; i < list.size(); i++) {
-			redisTemplate.opsForList().remove(key, -1,list.get(i));
-		}
-	}
 
+    // 删除
+    public static void del(String key) {
+        stringRedisTemplate.delete(key);
+    }
 
-	/* * * * * * * * * * * * * * * * Object值操作 * * * * * * * * * * * * * * * * * * * * * * * * */
 
-	// 写入值
-	public static void forValueSet(String key, Object value){
-		redisTemplate.opsForValue().set(key, value, ttl, TimeUnit.HOURS);
-	}
+    /* * * * * * * * * * * * * * * * List集合操作 * * * * * * * * * * * * * * * * * * * * * * * * */
 
-	// 读取值
-	@SuppressWarnings("unchecked")
-	public static <T>T forValueGet(String key, Class<T> cs){
-		return (T) redisTemplate.opsForValue().get(key);
-	}
+    // 查询
+    public static List<Object> forListGet(String key) {
+        return redisTemplate.opsForList().range(key, 0, -1);
+    }
 
+    // 追加键值
+    public static void forListAdd(String key, Object... args) {
+        redisTemplate.opsForList().rightPushAll(key, args);
+    }
 
+    // 移除所有键值
+    public static void forListRemove(String key) {
+        List<Object> list = forListGet(key);
+        for (int i = 0; i < list.size(); i++) {
+            redisTemplate.opsForList().remove(key, -1, list.get(i));
+        }
+    }
 
+    public static void forListRemove(String key, Object value) {
+        redisTemplate.opsForList().remove(key, 1, value);
+    }
 
 
+    /* * * * * * * * * * * * * * * * Object值操作 * * * * * * * * * * * * * * * * * * * * * * * * */
 
+    // 写入值
+    public static void forValueSet(String key, Object value) {
+        redisTemplate.opsForValue().set(key, value, ttl, TimeUnit.HOURS);
+    }
 
+    // 读取值
+    @SuppressWarnings("unchecked")
+    public static <T> T forValueGet(String key, Class<T> cs) {
+        return (T) redisTemplate.opsForValue().get(key);
+    }
 
 
 }

+ 10 - 0
sp-service/level-one-server/pom.xml

@@ -26,6 +26,16 @@
             <artifactId>sp-base</artifactId>
             <version>${project.parent.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.github.wechatpay-apiv3</groupId>
+            <artifactId>wechatpay-java</artifactId>
+            <version>0.2.14</version>
+        </dependency>
+        <dependency>
+            <groupId>com.github.binarywang</groupId>
+            <artifactId>weixin-java-pay</artifactId>
+            <version>4.6.0</version>
+        </dependency>
     </dependencies>
 
 </project>

+ 4 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrder.java

@@ -569,4 +569,8 @@ public class TbOrder extends Model<TbOrder> implements Serializable {
 	@TableField(exist = false)
 	private String phone;
 
+	/**
+	 * 是否扣除服务点费(0=未扣除,1=已扣除)
+	 */
+	private Integer isCheckoffWallet;
 }

+ 29 - 5
sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderAppController.java

@@ -1,13 +1,18 @@
 package com.pj.tb_order;
 
 import com.pj.api.dto.OrderDto;
+import com.pj.current.dto.APPLoginUserInfo;
 import com.pj.current.satoken.StpAPPUserUtil;
 import com.pj.project4sp.SP;
+import com.pj.project4sp.spcfg.SpCfgUtil;
 import com.pj.tb_order.vo.OrderVo;
 import com.pj.tb_order.vo.PeopleConfirmVo;
+import com.pj.tb_people.TbPeople;
+import com.pj.tb_people.TbPeopleService;
 import com.pj.utils.sg.AjaxJson;
 import com.pj.utils.so.SoMap;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.*;
 
 import java.util.Date;
@@ -26,7 +31,11 @@ public class TbOrderAppController {
 	@Autowired
 	TbOrderService tbOrderService;
 
-
+	/**
+	 * 底层 Service 对象
+	 */
+	@Autowired
+	TbPeopleService tbPeopleService;
 
 
 	/** 查 - 根据id */
@@ -73,6 +82,9 @@ public class TbOrderAppController {
 	 */
 	@RequestMapping("cancelOrder")
 	public AjaxJson cancelOrder(Long orderId) {
+		if (!StpAPPUserUtil.isLogin()){
+			return AjaxJson.getError("未登录");
+		}
 		boolean result = tbOrderService.cancelOrder(orderId);
 		if(result) return AjaxJson.getSuccess();
 		return AjaxJson.getError();
@@ -83,7 +95,9 @@ public class TbOrderAppController {
 	 */
 	@PostMapping("updateEnterpriseConfirm")
 	public AjaxJson updateEnterpriseConfirm(TbOrder order) {
-
+		if (!StpAPPUserUtil.isLogin()){
+			return AjaxJson.getError("未登录");
+		}
 		return AjaxJson.toAjax(tbOrderService.updateEnterpriseConfirm(order));
 	}
 
@@ -146,8 +160,18 @@ public class TbOrderAppController {
 
 	@RequestMapping("up")
 	public AjaxJson up(@RequestParam("id")Long id,@RequestParam("upPrice")String upPrice) {
-		tbOrderService.up(id,upPrice);
-		return AjaxJson.getSuccess();
+		APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
+		if(tbOrderService.getById(id).getIsCheckoffWallet().equals(0)) {
+			TbPeople tbPeople = tbPeopleService.getById(appLoginInfo.getFk());
+			if (tbPeople.getWallet() < SpCfgUtil.getTradeNum()) {
+				return AjaxJson.getError("剩余服务点数不足!");
+			}
+			tbOrderService.up(id,upPrice,tbPeople);
+			return AjaxJson.getSuccessData(SpCfgUtil.getTradeNum());
+		}else {
+			tbOrderService.up(id,upPrice,null);
+			return AjaxJson.getSuccessData(0);
+		}
 	}
 
 	@RequestMapping("down")
@@ -197,7 +221,7 @@ public class TbOrderAppController {
         return AjaxJson.toAjax(tbOrderService.orderRefund(id));
     }
 
-	/*-----           正常业务逻辑👆👆    rpc远程调用👇👇 -----*/
+	/*-----           正常业务逻辑    rpc远程调用 -----*/
 
 	/** 边民订单确认-收到银行扣款回执 */
 	@PostMapping("rpc/confirmOrderFromBank")

+ 1 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderMapper.xml

@@ -119,6 +119,7 @@
 			<if test=' this.has("returns") '> and returns = #{returns} </if>
 			<if test=' this.has("chargebacks") '> and chargebacks = #{chargebacks} </if>
 
+			<if test=' this.has("isCheckoffWallet") '> and is_checkoff_wallet = #{isCheckoffWallet} </if>
 			<if test='confirmType == "people_confirm_time" and this.has("dateBegin")'> and people_confirm_time &gt;= #{dateBegin} </if>
 			<if test='confirmType == "people_confirm_time" and this.has("dateEnd")'> and people_confirm_time &lt;= #{dateEnd} </if>
 

+ 42 - 9
sp-service/level-one-server/src/main/java/com/pj/tb_order/TbOrderService.java

@@ -28,6 +28,7 @@ import com.pj.current.satoken.StpAPPUserUtil;
 import com.pj.enummj.*;
 import com.pj.ht_trade_settlement.HtTradeSettlement;
 import com.pj.ht_trade_settlement.HtTradeSettlementService;
+import com.pj.project4sp.spcfg.SpCfgUtil;
 import com.pj.tb_enterprise.TbEnterprise;
 import com.pj.tb_enterprise.TbEnterpriseMapper;
 import com.pj.tb_goods_transit.TbGoodsTransit;
@@ -47,6 +48,9 @@ import com.pj.tb_shop.TbShop;
 import com.pj.tb_shop.TbShopService;
 import com.pj.tb_trade_area.TbTradeArea;
 import com.pj.tb_trade_area.TbTradeAreaService;
+import com.pj.tb_wallet_record.TbWalletRecord;
+import com.pj.tb_wallet_record.TbWalletRecordService;
+import com.pj.tb_wallet_topup.TbWalletTopupService;
 import com.pj.utils.sg.AjaxError;
 import com.pj.utils.so.SoMap;
 import io.swagger.models.auth.In;
@@ -107,8 +111,15 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
     private HtTradeSettlementService htTradeSettlementService;
     @Autowired
     private PaymentServerInterface paymentServerInterface;
+    @Resource
+    private TbWalletTopupService tbWalletTopupService;
+
+
+    /**
+     * 底层 Service 对象
+     */
     @Autowired
-    private TbTradeAreaService tbTradeAreaService;
+    TbWalletRecordService tbWalletRecordService;
 
     /**
      * 远程调用
@@ -116,12 +127,6 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
     @Autowired
     private AdminInterface adminInterface;
 
-    /**
-     * 删
-     */
-    void delete(Long id) {
-        removeById(id);
-    }
 
     /**
      * 改
@@ -1183,11 +1188,39 @@ public class TbOrderService extends ServiceImpl<TbOrderMapper, TbOrder> implemen
         return true;
     }
 
-    public void up(Long id, String upPrice) {
-        TbOrder tbOrder = this.getById(id);
+    public void up(Long id, String upPrice, TbPeople tbPeople) {
+        TbOrder tbOrder = super.getById(id);
         tbOrder.setId(id);
+        // -plj 2024-09-5 11:08:00 修改上架扣除服务点处理
+        if (tbPeople != null) {
+            tbOrder.setIsCheckoffWallet(1);   //1=已扣除
+        }
         tbOrder.setUpPrice(new BigDecimal(upPrice)).setUpTime(new Date()).setUpStatus(2);
         int i = tbOrderMapper.updateById(tbOrder);
+        if (i == 1 && tbPeople != null) {
+            double beforeAmount = tbPeople.getWallet();
+            int afterAmount = tbPeople.getWallet() - SpCfgUtil.getTradeNum();
+            Date date = new Date();
+            tbPeopleService.updateById(tbPeople.setWallet(afterAmount));
+            tbWalletRecordService.save(new TbWalletRecord()
+                    .setPeopleId(tbPeople.getId().toString())
+                    .setPeopleName(tbPeople.getName())
+                    .setVeNo(tbOrder.getVeNo())
+                    .setAmount(SpCfgUtil.getTradeNum().toString())
+                    .setBeforeAmount(beforeAmount)
+                    .setAfterAmount(afterAmount)
+                    .setOrderId(tbOrder.getId())
+                    .setTradeNo(tbOrder.getTradeNo())
+                    .setGoodsId(tbOrder.getGoodsId())
+                    .setGoodsNames(tbOrder.getGoodsNames())
+                    .setCreateTime(date).setRecordTime(date)
+                    .setCreateBy(StpAPPUserUtil.getAPPLoginInfo().getLoginId().toString())
+                    .setCreateName(StpAPPUserUtil.getAPPLoginInfo().getLoginName())
+                    .setDeleteStatus(DeleteStatus.DELETE_STATUS_ON.getCode())
+            );
+            tbWalletTopupService.subAmount(tbOrder.getBuyUserId());
+
+        }
         if (i != 1) {
             throw new AjaxError("上架失败");
         }

+ 74 - 67
sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeople.java

@@ -66,208 +66,208 @@ public class TbPeople extends Model<TbPeople> implements Serializable {
 	private String name;
 
 	/**
-	 * 边民号
+	 * 边民号 
 	 */
-	private String code;
+	private String code;	
 
 	/**
-	 * 性别(1=男,2=女)
+	 * 性别(1=男,2=女) 
 	 */
 	private Integer sex;
 
 	/**
-	 * 年龄
+	 * 年龄 
 	 */
-	private Integer age;
+	private Integer age;	
 
 	/**
-	 * 身份证
+	 * 身份证 
 	 */
 	private String idCard;
 
 	/**
-	 * 身份证复印件
+	 * 身份证复印件 
 	 */
-	private String idCardImg;
+	private String idCardImg;	
 
 	/**
-	 * 手机号码
+	 * 手机号码 
 	 */
 	private String phone;
 
 	/**
-	 * 银行编号
+	 * 银行编号 
 	 */
-	private String bankNo;
+	private String bankNo;	
 
 	/**
-	 * 银行卡号
+	 * 银行卡号 
 	 */
-	private String bankCode;
+	private String bankCode;	
 
 	/**
-	 * 银行名称
+	 * 银行名称 
 	 */
-	private String bankName;
+	private String bankName;	
 
 	/**
-	 * 所属互助组(1=测试组)
+	 * 所属互助组(1=测试组) 
 	 */
-	private Long groupId;
+	private Long groupId;	
 
 	/**
-	 * 互助组名称
+	 * 互助组名称 
 	 */
-	private String groupName;
+	private String groupName;	
 
 	/**
-	 * 是否可用(0=否,1=是)
+	 * 是否可用(0=否,1=是) 
 	 */
 	private Integer status;
 
 	/**
-	 * 角色(1=普通边民,2=兼组长)
+	 * 角色(1=普通边民,2=兼组长) 
 	 */
 	private Integer role;
 
 	/**
-	 * 经度
+	 * 经度 
 	 */
-	private Double lng;
+	private Double lng;	
 
 	/**
-	 * 纬度
+	 * 纬度 
 	 */
-	private Double lat;
+	private Double lat;	
 
 	/**
-	 * 最后一次下单定位
+	 * 最后一次下单定位 
 	 */
-	private String lastLocation;
+	private String lastLocation;	
 
 	/**
-	 * 联系地址
+	 * 联系地址 
 	 */
-	private String address;
+	private String address;	
 
 	/**
-	 * 地址ID
+	 * 地址ID 
 	 */
-	private String addressIds;
+	private String addressIds;	
 
 	/**
-	 * 详细地址
+	 * 详细地址 
 	 */
-	private String detailAddress;
+	private String detailAddress;	
 
 	/**
-	 * 是否锁定
+	 * 是否锁定 
 	 */
 	private Integer isLock;
 
 	/**
-	 * 当天剩余额度
+	 * 当天剩余额度 
 	 */
-	private Double leftPrice;
+	private Double leftPrice;	
 
 	/**
-	 * 审核状态
+	 * 审核状态 
 	 */
 	private Integer judgeStatus;
 
 	/**
-	 * 审核不通过内容
+	 * 审核不通过内容 
 	 */
-	private String judgeContent;
+	private String judgeContent;	
 
 	/**
-	 * 注册时间
+	 * 注册时间 
 	 */
 	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 	private Date registerTime;
 
 	/**
-	 * 审核时间
+	 * 审核时间 
 	 */
 	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 	private Date judgeTime;
 
 	/**
-	 * 审核人ID
+	 * 审核人ID 
 	 */
-	private String personId;
+	private String personId;	
 
 	/**
-	 * 创建时间
+	 * 创建时间 
 	 */
 	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 	private Date createTime;
 
 	/**
-	 * 创建人编号
+	 * 创建人编号 
 	 */
-	private String createBy;
+	private String createBy;	
 
 	/**
-	 * 创建人名称
+	 * 创建人名称 
 	 */
-	private String createName;
+	private String createName;	
 
 	/**
-	 * 更新时间
+	 * 更新时间 
 	 */
 	@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
 	private Date updateTime;
 
 	/**
-	 * 更新人编号
+	 * 更新人编号 
 	 */
-	private String updateBy;
+	private String updateBy;	
 
 	/**
-	 * 更新人名称
+	 * 更新人名称 
 	 */
-	private String updateName;
+	private String updateName;	
 
 	/**
-	 * 删除状态(0=禁用,1=启用)
+	 * 删除状态(0=禁用,1=启用) 
 	 */
-	private Integer deleteStatus;
+	private Integer deleteStatus;	
 
 	/**
-	 * 地方平台的内部业务编号,每次申请都是新编号
+	 * 地方平台的内部业务编号,每次申请都是新编号 
 	 */
-	private String platSeqNo;
+	private String platSeqNo;	
 
 	/**
-	 * 身份证有效期起,身份证有效期起必须小于身份证有效期止;格式:yyyy-MM-dd
+	 * 身份证有效期起,身份证有效期起必须小于身份证有效期止;格式:yyyy-MM-dd 
 	 */
 	@DateTimeFormat(pattern = "yyyy-MM-dd")
 	private Date startDate;
 
 	/**
-	 * 身份证有效期止,身份证有效期止必须大于身份证有效期起;格式:yyyy-MM-dd
+	 * 身份证有效期止,身份证有效期止必须大于身份证有效期起;格式:yyyy-MM-dd 
 	 */
 	@DateTimeFormat(pattern = "yyyy-MM-dd")
 	private Date endDate;
 
 	/**
-	 * 身份证发证机关
+	 * 身份证发证机关 
 	 */
-	private String idcdGcertPgoffNm;
+	private String idcdGcertPgoffNm;	
 
 	/**
-	 * 户籍地址
+	 * 户籍地址 
 	 */
-	private String birplAddr;
+	private String birplAddr;	
 
 	/**
-	 * 关区代码,参见关区代码表
+	 * 关区代码,参见关区代码表 
 	 */
-	private String customsCode;
+	private String customsCode;	
 
 	/**
-	 * 有 效 效 截 止 时 间yyyy-MM-dd
+	 * 有 效 效 截 止 时 间yyyy-MM-dd 
 	 */
 	@DateTimeFormat(pattern = "yyyy-MM-dd")
 	private Date expiry;
@@ -304,6 +304,13 @@ public class TbPeople extends Model<TbPeople> implements Serializable {
 
 
 
+	/**
+	 *  服务点
+	 */
+	private Integer wallet;
 
-
+	/**
+	 *  微信OpenId
+	 */
+	private String wxOpenId;
 }

+ 4 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeopleMapper.java

@@ -2,6 +2,8 @@ package com.pj.tb_people;
 
 import java.util.List;
 
+import cn.hutool.core.util.NumberUtil;
+import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
 import org.apache.ibatis.annotations.Mapper;
 
 import com.pj.utils.so.*;
@@ -34,4 +36,6 @@ public interface TbPeopleMapper extends BaseMapper <TbPeople> {
 	int updateApplyStatus(@Param("status") int status,@Param("peopleId") Long peopleId);
 	List<TbPeople> getLeftPeople();
 
+	void updatePeopleWallet(@Param("id") Long id, @Param("amount") Integer amount);
+
 }

+ 7 - 2
sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeopleMapper.xml

@@ -17,7 +17,7 @@
 			   p.group_id, p.group_name, p.status, p.role, p.lng, p.lat, p.last_location, p.address, p.address_ids,
 			   p.detail_address, p.is_lock, p.left_price, p.judge_status, p.judge_content, p.register_time, p.judge_time,
 			   p.person_id, p.create_time, p.create_by, p.create_name, p.update_time, p.update_by, p.update_name,
-			   p.delete_status, p.trade_area_id, p.trade_area_name
+			   p.delete_status, p.trade_area_id, p.trade_area_name,p.wallet,p.wx_open_id
 		from  tb_people p
 	</sql>
 
@@ -47,8 +47,13 @@
 		</where>
 
 	</update>
+    <update id="updatePeopleWallet">
+        update tb_people
+        set wallet=wallet + #{amount}
+        where id = #{id}
+    </update>
 
-	<select id="checkApplyExist" resultType="Integer">
+    <select id="checkApplyExist" resultType="Integer">
 		select  count(1) from tb_people_apply where people_id=#{peopleId} and status=0
 	</select>
 

+ 4 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_people/TbPeopleService.java

@@ -45,6 +45,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
+import org.yaml.snakeyaml.events.Event;
 
 import javax.annotation.Resource;
 import javax.swing.filechooser.FileSystemView;
@@ -810,4 +811,7 @@ public class TbPeopleService extends ServiceImpl<TbPeopleMapper, TbPeople> imple
     }
 
 
+    public void updatePeopleWallet(String id, Integer amount) {
+        tbPeopleMapper.updatePeopleWallet(Long.parseLong(id),amount);
+    }
 }

+ 368 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletAppController.java

@@ -0,0 +1,368 @@
+package com.pj.tb_wallet_record;
+
+import cn.dev33.satoken.spring.SpringMVCUtil;
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.core.util.XmlUtil;
+import cn.hutool.json.JSONUtil;
+import cn.hutool.log.StaticLog;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.github.binarywang.wxpay.bean.ecommerce.RefundsRequest;
+import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
+import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.bean.order.WxPayMpOrderResult;
+import com.github.binarywang.wxpay.bean.request.BaseWxPayRequest;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.constant.WxPayConstants;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.pj.common.core.utils.StringUtils;
+import com.pj.current.dto.APPLoginUserInfo;
+import com.pj.current.satoken.StpAPPUserUtil;
+import com.pj.enummj.DeleteStatus;
+import com.pj.tb_banner.TbBanner;
+import com.pj.tb_people.TbPeople;
+import com.pj.tb_people.TbPeopleService;
+import com.pj.tb_wallet_record.vo.NotifyBO;
+import com.pj.tb_wallet_record.vo.WalletRecordAppVo;
+import com.pj.tb_wallet_topdown.TbWalletTopdown;
+import com.pj.tb_wallet_topdown.TbWalletTopdownService;
+import com.pj.tb_wallet_topup.TbWalletTopup;
+import com.pj.tb_wallet_topup.TbWalletTopupService;
+import com.pj.utils.LogUtil;
+import com.pj.utils.cache.RedisUtil;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.sg.WebNbUtil;
+import com.pj.utils.so.SoMap;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.service.payments.app.AppService;
+import com.wechat.pay.java.service.payments.app.AppServiceExtension;
+import com.wechat.pay.java.service.payments.app.model.Amount;
+import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
+import com.wechat.pay.java.service.payments.app.model.PrepayResponse;
+import com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse;
+import io.swagger.models.auth.In;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.io.Writer;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+
+/**
+ * Controller: tb_wallet_record -- 服务点交易记录
+ *
+ * @author plj
+ */
+
+@RestController
+@RequestMapping("/app/WalletManage/")
+@Slf4j
+public class TbWalletAppController {
+
+    public static final String CZ_TABLE_NAME = "topup";
+    public static final String TX_TABLE_NAME = "topdown";
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbWalletRecordService tbWalletRecordService;
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbWalletTopupService tbWalletTopupService;
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbWalletTopdownService tbWalletTopdownService;
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbPeopleService tbPeopleService;
+
+
+    @Resource
+    private AppServiceExtension appServiceExtension;
+    @Resource
+    private WxPayProperties wxPayProperties;
+
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     *
+     * @return
+     */
+    @RequestMapping("getList")
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        Integer userType = StpAPPUserUtil.getAPPLoginInfo().getUserType();
+        if (userType == 1 || userType == 2) {
+            List<WalletRecordAppVo> list = tbWalletRecordService.getAPPList(so.startPage());
+            if (list.size() == 0) return AjaxJson.getSuccess("暂无更多的订单消息!");
+            return AjaxJson.getPageData(so.getDataCount(), list);
+        } else {
+            return AjaxJson.getError("暂无更多的订单消息!");
+        }
+    }
+
+
+    /**
+     * 查服务点充值 - 根据id
+     */
+    @RequestMapping("getTopUpById")
+    public AjaxJson getTopUpById(Long id) {
+        TbWalletTopup t = tbWalletTopupService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+
+    /**
+     * 查服务点提现- 根据id
+     */
+    @RequestMapping("getTopDownById")
+    public AjaxJson getTopDownById(Long id) {
+        TbWalletTopdown t = tbWalletTopdownService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+
+    /**
+     * 查服务点扣除 - 根据id
+     */
+    @RequestMapping("getWalletRecordById")
+    public AjaxJson getWalletRecordById(Long id) {
+        TbWalletRecord t = tbWalletRecordService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /*
+     * 服务点充值
+     */
+    @RequestMapping("topupSave")
+    public AjaxJson topupSave(@RequestParam("amount") Integer amount, @RequestParam("goodsName") String goodsName) {
+        //获取登录人
+        APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
+        TbPeople tbPeople = tbPeopleService.getById(appLoginInfo.getFk());
+        try {
+            TbWalletTopup tbWalletTopup = new TbWalletTopup();
+            Date date = new Date();
+            String tradeNo = CZ_TABLE_NAME + System.currentTimeMillis();
+            tbWalletTopup.setMchid(wxPayProperties.getMchId());
+            tbWalletTopup.setOutTradeNo(tradeNo);
+            tbWalletTopup.setGoodsName(goodsName);
+            tbWalletTopup.setAmount(amount);
+            tbWalletTopup.setBeforeAmount(tbPeople.getWallet());
+            tbWalletTopup.setAfterAmount(tbPeople.getWallet() + amount);
+            tbWalletTopup.setPeopleId(tbPeople.getId().toString());
+            tbWalletTopup.setTopupTime(date);
+            tbWalletTopup.setCreateTime(date);
+            tbWalletTopup.setCreateBy(appLoginInfo.getLoginId().toString());
+            tbWalletTopup.setCreateName(appLoginInfo.getLoginName());
+
+            PrepayWithRequestPaymentResponse response = prepay(tradeNo, BaseWxPayRequest.yuanToFen(tbWalletTopup.getAmount() + ""));
+//            StaticLog.info("response:{}",response);
+            // 付款中
+            tbWalletTopup.setPayStatus(1)
+                    .setPrepayid(response.getPrepayId());
+            tbWalletTopupService.save(tbWalletTopup);
+            Map<String, Object> result = new HashMap<>();
+            result.put("appid", response.getAppid());
+            result.put("noncestr", response.getNonceStr());
+            result.put("package", response.getPackageVal());
+            result.put("partnerid", response.getPartnerId());
+            result.put("prepayid", response.getPrepayId());
+            result.put("timestamp", response.getTimestamp());
+            result.put("sign", response.getSign());
+            RedisUtil.forListAdd(wxPayProperties.getMchId() + "-" + wxPayProperties.getAppId(), tradeNo + "-" + System.currentTimeMillis() / 1000);
+            return AjaxJson.getSuccessData(result);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return AjaxJson.getError("微信支付失败," + e.getMessage());
+        }
+    }
+
+    /**
+     * APP支付下单
+     */
+    public PrepayWithRequestPaymentResponse prepay(String tradeNo, Integer fee) {
+
+        PrepayRequest request = new PrepayRequest();
+        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+        request.setAppid(wxPayProperties.getAppId());
+        request.setMchid(wxPayProperties.getMchId());
+        request.setOutTradeNo(tradeNo);
+        request.setDescription(wxPayProperties.getGoodsDescription());
+        request.setNotifyUrl(wxPayProperties.getNotifyUrl());
+        Amount amount = new Amount();
+        amount.setTotal(1);
+        amount.setCurrency("CNY");
+        request.setAmount(amount);
+        // 调用接口
+        return appServiceExtension.prepayWithRequestPayment(request);
+    }
+
+
+    /*
+     * 服务点提现
+     */
+    @RequestMapping("topdownSave")
+    public AjaxJson topdownSave(@RequestParam("amount") Integer amount, @RequestParam("goodsName") String goodsName) {
+        //获取登录人
+        APPLoginUserInfo appLoginInfo = StpAPPUserUtil.getAPPLoginInfo();
+        TbPeople tbPeople = tbPeopleService.getById(appLoginInfo.getFk());
+        if (tbPeople.getWallet() < amount) {
+            return AjaxJson.getError("可提现点数不足!");
+        }
+        tbPeople.setWallet(tbPeople.getWallet() - amount);
+        try {
+            TbWalletTopdown tbWalletTopdown = new TbWalletTopdown();
+            Date date = new Date();
+            tbWalletTopdown.setMchid(wxPayProperties.getMchId());
+            tbWalletTopdown.setOutTradeNo(TX_TABLE_NAME + System.currentTimeMillis());
+            tbWalletTopdown.setGoodsName(goodsName);
+            tbWalletTopdown.setAmount(amount.toString());
+            tbWalletTopdown.setPeopleId(tbPeople.getId().toString());
+            tbWalletTopdown.setTopdownTime(date);
+            tbWalletTopdown.setCreateTime(date);
+            tbWalletTopdown.setCreateBy(appLoginInfo.getLoginId().toString());
+            tbWalletTopdown.setCreateName(appLoginInfo.getLoginName());
+
+            List<TbWalletTopup> list = tbWalletTopupService.findRefundList(tbPeople.getId());
+
+            for (TbWalletTopup tbWalletTopup : list) {
+                //剩余提现点数
+                int refundMoney = tbWalletTopup.getAmount() - tbWalletTopup.getCutCount() - tbWalletTopup.getRefundCount();
+                if (refundMoney > amount) {
+                    //提不完
+                    refundMoney = amount;
+                    tbWalletTopup.setRefundCount(amount);
+                    amount=0;
+                } else {
+                    tbWalletTopup.setRefundCount(refundMoney);
+                    amount = amount - refundMoney;
+                }
+                int total = BaseWxPayRequest.yuanToFen(tbWalletTopup.getAmount() + "");
+                RefundsRequest request = new RefundsRequest();
+                RefundsRequest.Amount refund = RefundsRequest.Amount.builder()
+                        .total(total)
+                        .currency("CNY")
+                        .refund(BaseWxPayRequest.yuanToFen(refundMoney + ""))
+                        .build();
+                request.setAmount(refund);
+                request.setTransactionId(tbWalletTopup.getTransactionId());
+                request.setOutTradeNo(tbWalletTopup.getOutTradeNo());
+                request.setReason("服务点提现");
+                request.setSpAppid(wxPayProperties.getAppId());
+                request.setSubMchid(wxPayProperties.getMchId());
+                request.setNotifyUrl(wxPayProperties.getNotifyUrl());
+                tbWalletTopupService.updateById(tbWalletTopup);
+                if (amount == 0) {
+                    break;
+                }
+            }
+            // 成功
+            tbWalletTopdown.setPayStatus(2);
+            tbWalletTopdownService.updateById(tbWalletTopdown);
+
+            tbPeopleService.updateById(tbPeople);
+            return AjaxJson.getSuccess();
+        } catch (Exception e) {
+            e.printStackTrace();
+            return AjaxJson.getError("提现失败," + e.getMessage());
+        }
+
+    }
+
+    /**
+     * 微信支付回调接口
+     *
+     * @return
+     */
+    @RequestMapping(value = "/wxPay/notify", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
+    public void notify(HttpServletRequest request, HttpServletResponse response) {
+        try {
+            request.setCharacterEncoding("UTF-8");
+            response.setCharacterEncoding("UTF-8");
+            response.setContentType("text/html;charset=UTF-8");
+            response.setHeader("Access-Control-Allow-Origin", "*");
+            InputStream in = request.getInputStream();
+            ByteArrayOutputStream out = new ByteArrayOutputStream();
+            byte[] buffer = new byte[1024];
+            int len = 0;
+            while ((len = in.read(buffer)) != -1) {
+                out.write(buffer, 0, len);
+            }
+            out.close();
+            in.close();
+            //xml数据
+            String reponseXml = new String(out.toByteArray(), "utf-8");
+//            WxPayOrderNotifyResult result = wxService.parseOrderNotifyResult(reponseXml);
+            WxPayOrderNotifyResult result = null;
+            String resultCode = result.getResultCode();
+            String outTradeNo = result.getOutTradeNo();
+            if ("FAIL".equalsIgnoreCase(resultCode)) {
+                LogUtil.info("订单" + outTradeNo + "支付失败");
+                response.getWriter().write(setXml("SUCCESS", "OK"));
+            } else if ("SUCCESS".equalsIgnoreCase(resultCode)) {
+                LogUtil.info("订单" + outTradeNo + "支付成功");
+                // 充值数据处理
+                if (outTradeNo.indexOf(CZ_TABLE_NAME) > -1) {
+                    QueryWrapper<TbWalletTopup> queryWrapper = new QueryWrapper<>();
+                    queryWrapper.eq("outTradeNo", outTradeNo);
+                    TbWalletTopup tbWalletTopup = tbWalletTopupService.list(queryWrapper).get(0);
+                    tbWalletTopup.setPayStatus(2);
+                    tbWalletTopupService.updateById(tbWalletTopup);
+
+                    TbPeople tbPeople = tbPeopleService.getById(tbWalletTopup.getPeopleId());
+                    tbPeople.setWallet(tbPeople.getWallet() + tbWalletTopup.getAmount());
+                    tbPeopleService.updateById(tbPeople);
+                }
+                response.getWriter().write(setXml("SUCCESS", "OK"));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    //返回微信服务
+    public static String setXml(String returnCode, String returnMsg) {
+        return "<xml><return_code><![CDATA[" + returnCode + "]]></return_code><return_msg><![CDATA[" + returnMsg + "]]></return_msg></xml>";
+    }
+
+    @RequestMapping(value = "notify")
+    public void notify(@RequestBody NotifyBO notifyBO, HttpServletResponse response) throws Exception {
+        log.info("wx pay notify;{}", JSONUtil.toJsonStr(notifyBO));
+        response.setContentType("application/json");
+        response.setCharacterEncoding("UTF-8");
+        Writer writer = response.getWriter();
+        Map<String, String> result = new HashMap<>();
+        result.put("return_code", "SUCCESS");
+        result.put("return_msg", "OK");
+        notifyBO.setTradeStatus("SUCCESS");
+        tbWalletTopupService.WxNotify(notifyBO);
+        writer.write(XmlUtil.mapToXmlStr(result));
+        writer.flush();
+        writer.close();
+    }
+}
+
+
+

+ 138 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecord.java

@@ -0,0 +1,138 @@
+package com.pj.tb_wallet_record;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_wallet_record -- 服务点交易记录
+ * @author plj 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbWalletRecord.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbWalletRecord extends Model<TbWalletRecord> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_wallet_record";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-wallet-record";
+	public static final String PERMISSION_CODE_ADD = "tb-wallet-record-add";
+	public static final String PERMISSION_CODE_EDIT = "tb-wallet-record-edit";
+	public static final String PERMISSION_CODE_DEL = "tb-wallet-record-del";
+
+
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 边民id 
+	 */
+	private String peopleId;
+	/**
+	 * 边民
+	 */
+	private String peopleName;
+	/**
+	 * 车牌
+	 */
+	private String veNo;
+
+	/**
+	 * 交易前点数 
+	 */
+	private double beforeAmount;
+
+	/**
+	 * 交易后点数 
+	 */
+	private double afterAmount;
+
+	/**
+	 * 交易扣除点数 
+	 */
+	private String amount;
+
+	/**
+	 * 关联订单号主键
+	 */
+	private Long orderId;
+	/**
+	 * 关联订单号 
+	 */
+	private String tradeNo;	
+
+	/**
+	 * 关联商品id 
+	 */
+	private Long goodsId;	
+
+	/**
+	 * 关联商品名称 
+	 */
+	private String goodsNames;	
+
+	/**
+	 * 扣除时间 
+	 */
+	private Date recordTime;
+
+	/**
+	 * 创建人编号 
+	 */
+	private String createBy;	
+
+	/**
+	 * 创建人名称 
+	 */
+	private String createName;	
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+	/**
+	 * 更新人编号 
+	 */
+	private String updateBy;	
+
+	/**
+	 * 更新人名称 
+	 */
+	private String updateName;	
+
+	/**
+	 * 更新时间 
+	 */
+	private Date updateTime;
+
+	/**
+	 * 删除状态(0=禁用,1=启用) 
+	 */
+	private Integer deleteStatus;
+
+
+}

+ 58 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordController.java

@@ -0,0 +1,58 @@
+package com.pj.tb_wallet_record;
+
+import java.util.List;
+
+import com.pj.tb_wallet_record.vo.WalletRecordVo;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_wallet_record -- 服务点交易记录
+ *
+ * @author plj
+ */
+@RestController
+@RequestMapping("/TbWalletRecord/")
+public class TbWalletRecordController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbWalletRecordService tbWalletRecordService;
+
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    @SaCheckPermission(TbWalletRecord.PERMISSION_CODE)
+    public AjaxJson getById(Long id) {
+        TbWalletRecord t = tbWalletRecordService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    @SaCheckPermission(TbWalletRecord.PERMISSION_CODE)
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        List<TbWalletRecord> list = tbWalletRecordService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+
+
+
+
+}

+ 39 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordMapper.java

@@ -0,0 +1,39 @@
+package com.pj.tb_wallet_record;
+
+import java.util.List;
+
+import com.pj.tb_order.TbOrder;
+import com.pj.tb_wallet_record.vo.WalletRecordAppVo;
+import com.pj.tb_wallet_record.vo.WalletRecordVo;
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_wallet_record -- 服务点交易记录
+ * @author plj 
+ */
+
+@Mapper
+@Repository
+public interface TbWalletRecordMapper extends BaseMapper <TbWalletRecord> {
+
+
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * @param so 参数集合 
+	 * @return 数据列表 
+	 */
+	List<TbWalletRecord> getList(SoMap so);
+
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * @param so 参数集合
+	 * @return 数据列表
+	 */
+	List<WalletRecordAppVo> getAppList(SoMap so);
+}

+ 79 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordMapper.xml

@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.tb_wallet_record.TbWalletRecordMapper">
+
+
+	<!-- 通用映射:自动模式 -->
+	<resultMap id="model" autoMapping="true" type="com.pj.tb_wallet_record.vo.WalletRecordVo"></resultMap>
+
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select w.*,p.name as peopleName
+		from tb_wallet_record as w
+		left join tb_people as p on w.people_id = p.id
+	</sql>
+
+	
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		select * from tb_wallet_record as w
+		<where>
+			<if test=' this.has("id") '> and w.id = #{id} </if>
+			<if test=' this.has("peopleId") '> and w.people_id = #{peopleId} </if>
+			<if test=' this.has("peopleName") '> and w.people_name like concat ('%',#{peopleName},'%')  </if>
+			<if test=' this.has("veNo") '> and w.ve_no like concat ('%',#{veNo},'%')  </if>
+			<if test=' this.has("beforeAmount") '> and w.before_amount = #{beforeAmount} </if>
+			<if test=' this.has("afterAmount") '> and w.after_amount = #{afterAmount} </if>
+			<if test=' this.has("amount") '> and w.amount = #{amount} </if>
+			<if test=' this.has("orderId") '> and w.order_id = #{orderId} </if>
+			<if test=' this.has("tradeNo") '> and w.trade_no = #{tradeNo} </if>
+			<if test=' this.has("goodsId") '> and w.goods_id = #{goodsId} </if>
+			<if test=' this.has("goodsNames") '> and w.goods_names like concat ('%',#{goodsNames},'%') </if>
+			<if test=' this.has("recordTime") '> and w.record_time = #{recordTime} </if>
+			<if test=' this.has("createBy") '> and w.create_by = #{createBy} </if>
+			<if test=' this.has("createName") '> and w.create_name = #{createName} </if>
+			<if test=' this.has("createTime") '> and w.create_time = #{createTime} </if>
+			<if test=' this.has("updateBy") '> and w.update_by = #{updateBy} </if>
+			<if test=' this.has("updateName") '> and w.update_name = #{updateName} </if>
+			<if test=' this.has("updateTime") '> and w.update_time = #{updateTime} </if>
+			<if test=' this.has("deleteStatus") '> and w.delete_status = #{deleteStatus} </if>
+			<if test=' this.has("peopleName") '> and p.name = #{peopleName} </if>
+		</where>
+		order by
+		<choose>
+			<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> people_id desc </when>
+			<when test='sortType == 3'> before_amount desc </when>
+			<when test='sortType == 4'> after_amount desc </when>
+			<when test='sortType == 5'> amount desc </when>
+			<when test='sortType == 6'> trade_no desc </when>
+			<when test='sortType == 7'> goods_id desc </when>
+			<when test='sortType == 8'> goods_names desc </when>
+			<when test='sortType == 9'> record_time desc </when>
+			<when test='sortType == 10'> create_by desc </when>
+			<when test='sortType == 11'> create_name desc </when>
+			<when test='sortType == 12'> create_time desc </when>
+			<when test='sortType == 13'> update_by desc </when>
+			<when test='sortType == 14'> update_name desc </when>
+			<when test='sortType == 15'> update_time desc </when>
+			<when test='sortType == 16'> delete_status desc </when>
+			<otherwise> id desc </otherwise>
+		</choose>
+	</select>
+
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getAppList" resultType="com.pj.tb_wallet_record.vo.WalletRecordAppVo">
+		select w.*,p.name as peopleName
+		from v_wallet_record as w
+		left join tb_people as p on w.people_id = p.id
+		<where>
+			<if test=' this.has("peopleId") '> and w.people_id = #{peopleId} </if>
+			<if test=' this.has("peopleName") '> and p.name = #{peopleName} </if>
+			<if test=' this.has("tagType") '> and w.tag_type = #{tagType} </if>
+			<if test=' this.has("status") '> and w.status = #{status} </if>
+		</where>
+		order by  record_time desc
+	</select>
+	
+
+</mapper>

+ 70 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/TbWalletRecordService.java

@@ -0,0 +1,70 @@
+package com.pj.tb_wallet_record;
+
+import java.util.List;
+
+import com.pj.current.dto.APPLoginUserInfo;
+import com.pj.current.satoken.StpAPPUserUtil;
+import com.pj.tb_order.TbOrder;
+import com.pj.tb_wallet_record.vo.WalletRecordAppVo;
+import com.pj.tb_wallet_record.vo.WalletRecordVo;
+import com.pj.utils.so.SoMap;
+import com.wechat.pay.java.service.payments.app.AppServiceExtension;
+import com.wechat.pay.java.service.payments.app.model.QueryOrderByIdRequest;
+import com.wechat.pay.java.service.payments.model.Transaction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+
+/**
+ * Service: tb_wallet_record -- 服务点交易记录
+ * @author plj 
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+@Slf4j
+public class TbWalletRecordService extends ServiceImpl<TbWalletRecordMapper, TbWalletRecord> implements IService<TbWalletRecord>{
+
+	/** 底层 Mapper 对象 */
+	@Autowired
+	TbWalletRecordMapper tbWalletRecordMapper;
+	@Autowired
+    WxPayProperties wxPayProperties;
+
+
+
+
+
+	/** 查 */
+	TbWalletRecord getById(Long id){
+		List<TbWalletRecord> listObj=tbWalletRecordMapper.getList(new SoMap().set("id",id));
+		if(listObj!=null && listObj.size()>0) {
+			return listObj.get(0);
+		}else {
+			return  null;
+		}
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	List<TbWalletRecord> getList(SoMap so) {
+		return tbWalletRecordMapper.getList(so);
+	}
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * APP专用 获取服务点关联记录包括充值、提现、扣除
+	 *
+	 * @param so
+	 * @return
+	 */
+	List<WalletRecordAppVo> getAPPList(SoMap so) {
+		return tbWalletRecordMapper.getAppList(so);
+	}
+
+
+
+}

+ 63 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/WxPayConfiguration.java

@@ -0,0 +1,63 @@
+package com.pj.tb_wallet_record;
+
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.service.payments.app.AppService;
+import com.wechat.pay.java.service.payments.app.AppServiceExtension;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author plj
+ */
+@Configuration
+@ConditionalOnClass(WxPayService.class)
+@EnableConfigurationProperties(WxPayProperties.class)
+@AllArgsConstructor
+public class WxPayConfiguration {
+  @Autowired
+  private WxPayProperties properties;
+
+  @Bean
+  @ConditionalOnMissingBean
+  public WxPayService wxService() {
+    WxPayConfig payConfig = new WxPayConfig();
+    payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
+    payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
+    payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
+    payConfig.setTradeType(StringUtils.trimToNull(this.properties.getTradeType()));
+    payConfig.setApiV3Key(StringUtils.trimToNull(this.properties.getApiV3Key()));
+    payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
+    payConfig.setNotifyUrl(StringUtils.trimToNull(this.properties.getNotifyUrl()));
+
+    // 可以指定是否使用沙箱环境
+    payConfig.setUseSandboxEnv(false);
+
+    WxPayService wxPayService = new WxPayServiceImpl();
+    wxPayService.setConfig(payConfig);
+    return wxPayService;
+  }
+
+  @Bean
+  public AppServiceExtension service(){
+    // 初始化商户配置
+    Config config =
+            new RSAAutoCertificateConfig.Builder()
+                    .merchantId(StringUtils.trimToNull(properties.getMchId()))
+                    // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
+                    .privateKeyFromPath(properties.getKeyPath())
+                    .merchantSerialNumber(StringUtils.trimToNull(properties.getSerialNumber()))
+                    .apiV3Key(properties.getApiV3Key())
+                    .build();
+   return new AppServiceExtension.Builder().config(config).build();
+  }
+}

+ 53 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/WxPayProperties.java

@@ -0,0 +1,53 @@
+package com.pj.tb_wallet_record;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * wxpay pay properties.
+ * @author plj
+ */
+@Data
+@ConfigurationProperties(prefix = "wx")
+public class WxPayProperties {
+  /**
+   * 设置微信公众号或者小程序等的appid
+   */
+  private String appId;
+
+  /**
+   * 微信支付商户号
+   */
+  private String mchId;
+  /**
+   * 证书序列号
+   */
+  private String serialNumber;
+
+  /**
+   * 微信支付商户密钥
+   */
+  private String mchKey;
+
+  /**
+   * 交易类型 JSAPI、APP
+   */
+  private String tradeType;
+
+  /**
+   * APIv3密钥
+   */
+  private String apiV3Key;
+
+  /**
+   * apiclient_cert.p12文件的绝对路径,或者如果放在项目中,请以classpath:开头指定
+   */
+  private String keyPath;
+
+  private String goodsDescription;
+
+  /**
+   * 支付回调地址
+   */
+  private String notifyUrl;
+}

+ 103 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/app/AppServiceExample.java

@@ -0,0 +1,103 @@
+package com.pj.tb_wallet_record.app;
+
+import cn.hutool.core.util.RandomUtil;
+import cn.hutool.json.JSONUtil;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.core.exception.HttpException;
+import com.wechat.pay.java.core.exception.MalformedMessageException;
+import com.wechat.pay.java.core.exception.ServiceException;
+import com.wechat.pay.java.service.payments.app.AppService;
+import com.wechat.pay.java.service.payments.app.model.*;
+import com.wechat.pay.java.service.payments.model.Transaction;
+
+/** AppService使用示例 */
+public class AppServiceExample {
+
+  /** 商户号 */
+  public static String merchantId = "1695540177";
+
+  /** 商户API私钥路径 */
+  public static String privateKeyPath = "E:\\libs\\wx\\apiclient_key.pem";
+
+  /** 商户证书序列号 */
+  public static String merchantSerialNumber = "5469DA5ED227341CF27A93AE1D31811D6965A139";
+
+  /** 商户APIV3密钥 */
+  public static String apiV3Key = "r73q9l7im6qtle33eua3l5ogp6lahss8";
+
+  public static AppService service;
+
+  public static void main(String[] args) {
+    // 初始化商户配置
+    Config config =
+        new RSAAutoCertificateConfig.Builder()
+            .merchantId(merchantId)
+            // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
+            .privateKeyFromPath(privateKeyPath)
+            .merchantSerialNumber(merchantSerialNumber)
+            .apiV3Key(apiV3Key)
+            .build();
+
+    // 初始化服务
+    service = new AppService.Builder().config(config).build();
+    // ... 调用接口
+    try {
+      PrepayResponse response=prepay();
+      System.out.println("prepay response: " + JSONUtil.toJsonStr(response));
+    } catch (HttpException e) { // 发送HTTP请求失败
+      e.printStackTrace();
+      // 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义
+    } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
+      e.printStackTrace();
+      // 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
+    } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
+      e.printStackTrace();
+      // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义
+    }
+  }
+
+  /** 关闭订单 */
+  public static void closeOrder() {
+
+    CloseOrderRequest request = new CloseOrderRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+    // 调用接口
+    service.closeOrder(request);
+  }
+
+  /** APP支付下单 */
+  public static PrepayResponse prepay() {
+    PrepayRequest request = new PrepayRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+    request.setAppid("wx0daaef365288a0db");
+    request.setMchid(merchantId);
+    request.setOutTradeNo(RandomUtil.randomString(16));
+    request.setDescription("Image形象店-深圳腾大-QQ公仔");
+    request.setNotifyUrl("http://hs-server.tbgjhc.top:8018/level-one-server/TbPeople/getList");
+    Amount amount=new Amount();
+    amount.setTotal(1);
+    amount.setCurrency("CNY");
+    request.setAmount(amount);
+    // 调用接口
+    return service.prepay(request);
+  }
+
+  /** 微信支付订单号查询订单 */
+  public static Transaction queryOrderById() {
+
+    QueryOrderByIdRequest request = new QueryOrderByIdRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+    // 调用接口
+    return service.queryOrderById(request);
+  }
+
+  /** 商户订单号查询订单 */
+  public static Transaction queryOrderByOutTradeNo() {
+
+    QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+    // 调用接口
+    return service.queryOrderByOutTradeNo(request);
+  }
+}

+ 93 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/app/AppServiceExtensionExample.java

@@ -0,0 +1,93 @@
+package com.pj.tb_wallet_record.app;
+
+import com.github.binarywang.wxpay.bean.ecommerce.RefundsRequest;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAAutoCertificateConfig;
+import com.wechat.pay.java.core.exception.HttpException;
+import com.wechat.pay.java.core.exception.MalformedMessageException;
+import com.wechat.pay.java.core.exception.ServiceException;
+import com.wechat.pay.java.service.payments.app.AppServiceExtension;
+import com.wechat.pay.java.service.payments.app.model.CloseOrderRequest;
+import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
+import com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse;
+import com.wechat.pay.java.service.payments.app.model.QueryOrderByIdRequest;
+import com.wechat.pay.java.service.payments.app.model.QueryOrderByOutTradeNoRequest;
+import com.wechat.pay.java.service.payments.model.Transaction;
+
+public class AppServiceExtensionExample {
+  /** 商户号 */
+  public static String merchantId = "190000****";
+
+  /** 商户API私钥路径 */
+  public static String privateKeyPath = "/Users/yourname/your/path/apiclient_key.pem";
+
+  /** 商户证书序列号 */
+  public static String merchantSerialNumber = "5157F09EFDC096DE15EBE81A47057A72********";
+
+  /** 商户APIV3密钥 */
+  public static String apiV3Key = "...";
+
+  public static AppServiceExtension service;
+
+  public static void main(String[] args) {
+    // 初始化商户配置
+    Config config =
+        new RSAAutoCertificateConfig.Builder()
+            .merchantId(merchantId)
+            // 使用 com.wechat.pay.java.core.util 中的函数从本地文件中加载商户私钥,商户私钥会用来生成请求的签名
+            .privateKeyFromPath(privateKeyPath)
+            .merchantSerialNumber(merchantSerialNumber)
+            .apiV3Key(apiV3Key)
+            .build();
+    // 初始化服务
+    service = new AppServiceExtension.Builder().config(config).build();
+    try {
+      // ... 调用接口
+      PrepayWithRequestPaymentResponse response = prepayWithRequestPayment();
+      System.out.println(response);
+    } catch (HttpException e) { // 发送HTTP请求失败
+      // 调用e.getHttpRequest()获取请求打印日志或上报监控,更多方法见HttpException定义
+    } catch (ServiceException e) { // 服务返回状态小于200或大于等于300,例如500
+      // 调用e.getResponseBody()获取返回体打印日志或上报监控,更多方法见ServiceException定义
+    } catch (MalformedMessageException e) { // 服务返回成功,返回体类型不合法,或者解析返回体失败
+      // 调用e.getMessage()获取信息打印日志或上报监控,更多方法见MalformedMessageException定义
+    }
+  }
+
+  /** 关闭订单 */
+  public static void closeOrder() {
+
+
+    CloseOrderRequest request = new CloseOrderRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+    // 调用接口
+    service.closeOrder(request);
+  }
+
+  /** APP支付下单,并返回APP调起支付数据 */
+  public static PrepayWithRequestPaymentResponse prepayWithRequestPayment() {
+    PrepayRequest request = new PrepayRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+    // 调用接口
+    return service.prepayWithRequestPayment(request);
+  }
+
+  /** 微信支付订单号查询订单 */
+  public static Transaction queryOrderById() {
+
+    QueryOrderByIdRequest request = new QueryOrderByIdRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+
+    // 调用接口
+    return service.queryOrderById(request);
+  }
+
+  /** 商户订单号查询订单 */
+  public static Transaction queryOrderByOutTradeNo() {
+
+    QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
+    // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+    // 调用接口
+    return service.queryOrderByOutTradeNo(request);
+  }
+}

+ 47 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/vo/NotifyBO.java

@@ -0,0 +1,47 @@
+package com.pj.tb_wallet_record.vo;
+
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
+import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+@JacksonXmlRootElement(localName = "xml")
+@Data
+@Accessors(chain = true)
+public class NotifyBO {
+
+
+    // 返回状态码
+    @JacksonXmlProperty(localName = "return_code")
+    private String returnCode;
+
+    // 返回信息
+    @JacksonXmlProperty(localName = "return_msg")
+    private String returnMsg;
+
+    // 业务结果
+    @JacksonXmlProperty(localName = "result_code")
+    private String resultCode;
+
+    // 商户订单号
+    @JacksonXmlProperty(localName = "out_trade_no")
+    private String outTradeNo;
+
+    // 支付完成时间
+    @JacksonXmlProperty(localName = "time_end")
+    private String timeEnd;
+
+    // 微信支付订单号
+    @JacksonXmlProperty(localName = "transaction_id")
+    private String transactionId;
+
+    // 订单金额
+    @JacksonXmlProperty(localName = "total_fee")
+    private String totalFee;
+    @JacksonXmlProperty(localName = "attach")
+    private String attach;
+
+    @JacksonXmlProperty(localName = "result_code")
+    private String tradeStatus;
+
+}

+ 42 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/vo/WalletRecordAppVo.java

@@ -0,0 +1,42 @@
+package com.pj.tb_wallet_record.vo;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import io.swagger.models.auth.In;
+import lombok.Data;
+
+@Data
+public class WalletRecordAppVo {
+    /**
+     * 主键
+     */
+    @TableId(type = IdType.AUTO)
+    private Long id;
+
+    /**
+     * 标签类型(0=全部,1=充值,2=提现,3=扣除)
+     */
+    private String tagType;
+
+
+    /**
+     * 支标签类型名称
+     */
+    private String tagTypeName;
+
+    /**
+     * 边民id
+     */
+    private String peopleId;
+
+    /**
+     * 交易扣除点数
+     */
+    private Integer amount;
+    private Integer status;
+
+    /**
+     * 扣除时间
+     */
+    private String recordTime;
+}

+ 12 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_record/vo/WalletRecordVo.java

@@ -0,0 +1,12 @@
+package com.pj.tb_wallet_record.vo;
+
+import com.pj.tb_wallet_record.TbWalletRecord;
+
+/**
+ * Model: tb_wallet_record -- 服务点交易记录
+ * @author plj
+ */
+public class WalletRecordVo extends TbWalletRecord {
+
+
+}

+ 118 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/EntPayController.java

@@ -0,0 +1,118 @@
+package com.pj.tb_wallet_topdown;
+
+import com.github.binarywang.wxpay.bean.entpay.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * 企业付款相关接口
+ * @author plj
+ */
+
+@RestController
+@RequestMapping("/EntPay/")
+public class EntPayController {
+  @Autowired
+  private WxPayService wxService;
+
+  /**
+   * <pre>
+   * 企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。
+   * 比如目前的保险行业向客户退保、给付、理赔。
+   * 企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”https://pay.weixin.qq.com/进行操作。
+   * 注意:与商户微信支付收款资金并非同一账户,需要单独充值。
+   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
+   * 接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
+   * </pre>
+   *
+   * @param request 请求对象
+   */
+  @ApiOperation(value = "企业付款到零钱")
+  @PostMapping("/entPay")
+  public EntPayResult entPay(@RequestBody EntPayRequest request) throws WxPayException {
+    return this.wxService.getEntPayService().entPay(request);
+  }
+
+  /**
+   * <pre>
+   * 查询企业付款API
+   * 用于商户的企业付款操作进行结果查询,返回付款操作详细结果。
+   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
+   * 接口链接:https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo
+   * </pre>
+   *
+   * @param partnerTradeNo 商户订单号
+   */
+  @ApiOperation(value = "查询企业付款到零钱的结果")
+  @GetMapping("/queryEntPay/{partnerTradeNo}")
+  public EntPayQueryResult queryEntPay(@PathVariable String partnerTradeNo) throws WxPayException {
+    return this.wxService.getEntPayService().queryEntPay(partnerTradeNo);
+  }
+
+
+  /**
+   * <pre>
+   * 获取RSA加密公钥API.
+   * RSA算法使用说明(非对称加密算法,算法采用RSA/ECB/OAEPPadding模式)
+   * 1、 调用获取RSA公钥API获取RSA公钥,落地成本地文件,假设为public.pem
+   * 2、 确定public.pem文件的存放路径,同时修改代码中文件的输入路径,加载RSA公钥
+   * 3、 用标准的RSA加密库对敏感信息进行加密,选择RSA_PKCS1_OAEP_PADDING填充模式
+   * (eg:Java的填充方式要选 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING")
+   * 4、 得到进行rsa加密并转base64之后的密文
+   * 5、 将密文传给微信侧相应字段,如付款接口(enc_bank_no/enc_true_name)
+   *
+   * 接口默认输出PKCS#1格式的公钥,商户需根据自己开发的语言选择公钥格式
+   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
+   * 接口链接:https://fraud.mch.weixin.qq.com/risk/getpublickey
+   * </pre>
+   *
+   * @return the public key
+   * @throws WxPayException the wx pay exception
+   */
+  @ApiOperation(value = "获取RSA加密公钥")
+  @GetMapping("/getPublicKey")
+  public String getPublicKey() throws WxPayException {
+    return this.wxService.getEntPayService().getPublicKey();
+  }
+
+  /**
+   * 企业付款到银行卡.
+   * <pre>
+   * 用于企业向微信用户银行卡付款
+   * 目前支持接口API的方式向指定微信用户的银行卡付款。
+   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2
+   * 接口链接:https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
+   * </pre>
+   *
+   * @param request 请求对象
+   * @return the ent pay bank result
+   * @throws WxPayException the wx pay exception
+   */
+  @ApiOperation(value = "企业付款到银行卡")
+  @PostMapping("/payBank")
+  public EntPayBankResult payBank(EntPayBankRequest request) throws WxPayException {
+    return this.wxService.getEntPayService().payBank(request);
+  }
+
+  /**
+   * 企业付款到银行卡查询.
+   * <pre>
+   * 用于对商户企业付款到银行卡操作进行结果查询,返回付款操作详细结果。
+   * 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3
+   * 接口链接:https://api.mch.weixin.qq.com/mmpaysptrans/query_bank
+   * </pre>
+   *
+   * @param partnerTradeNo 商户订单号
+   * @return the ent pay bank query result
+   * @throws WxPayException the wx pay exception
+   */
+  @ApiOperation(value = "查询企业付款到银行卡的结果")
+  @GetMapping("/queryPayBank/{partnerTradeNo}")
+  public EntPayBankQueryResult queryPayBank(@PathVariable String partnerTradeNo) throws WxPayException {
+    return this.wxService.getEntPayService().queryPayBank(partnerTradeNo);
+  }
+
+}

+ 121 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdown.java

@@ -0,0 +1,121 @@
+package com.pj.tb_wallet_topdown;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_wallet_topdown -- 服务点提现记录
+ * @author plj 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbWalletTopdown.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbWalletTopdown extends Model<TbWalletTopdown> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_wallet_topdown";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-wallet-topdown";
+	public static final String PERMISSION_CODE_ADD = "tb-wallet-topdown-add";
+	public static final String PERMISSION_CODE_EDIT = "tb-wallet-topdown-edit";
+	public static final String PERMISSION_CODE_DEL = "tb-wallet-topdown-del";
+
+
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 边民id 
+	 */
+	private String peopleId;	
+
+	/**
+	 * 商户号 
+	 */
+	private String mchid;	
+
+	/**
+	 * 商户系统内部订单号 
+	 */
+	private String outTradeNo;	
+
+	/**
+	 * 微信支付系统生成的订单号 
+	 */
+	private String transactionId;
+
+	/**
+	 * 商品名称
+	 */
+	private String goodsName;
+
+	/**
+	 * 提现金额 
+	 */
+	private String amount;	
+
+	/**
+	 * 提现时间 
+	 */
+	private Date topdownTime;
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+	/**
+	 * 创建人编号 
+	 */
+	private String createBy;	
+
+	/**
+	 * 创建人名称 
+	 */
+	private String createName;	
+
+	/**
+	 * 更新时间 
+	 */
+	private Date updateTime;
+
+	/**
+	 * 更新人编号 
+	 */
+	private String updateBy;	
+
+	/**
+	 * 更新人名称 
+	 */
+	private String updateName;	
+
+	/**
+	 * 支付状态(0=未支付,1=支付中,2=已支付)
+	 */
+	private Integer payStatus;
+
+
+}

+ 87 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownController.java

@@ -0,0 +1,87 @@
+package com.pj.tb_wallet_topdown;
+
+import java.util.List;
+import com.pj.tb_wallet_topdown.vo.WalletTopdownVo;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.pj.utils.sg.*;
+import com.pj.project4sp.SP;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_wallet_topdown -- 服务点提现记录
+ * @author plj 
+ */
+@RestController
+@RequestMapping("/TbWalletTopdown/")
+public class TbWalletTopdownController {
+
+	/** 底层 Service 对象 */
+	@Autowired
+	TbWalletTopdownService tbWalletTopdownService;
+
+	/** 增 */  
+	@RequestMapping("add")
+	@SaCheckPermission(TbWalletTopdown.PERMISSION_CODE_ADD)
+	public AjaxJson add(TbWalletTopdown t){
+		tbWalletTopdownService.add(t);
+		t = tbWalletTopdownService.getById(SP.publicMapper.getPrimarykey());
+		return AjaxJson.getSuccessData(t);
+	}
+
+	/** 删 */  
+	@RequestMapping("delete")
+	@SaCheckPermission(TbWalletTopdown.PERMISSION_CODE_DEL)
+	public AjaxJson delete(Long id){
+		 tbWalletTopdownService.delete(id);
+		return AjaxJson.getSuccess();
+	}
+	
+	/** 删 - 根据id列表 */  
+	@RequestMapping("deleteByIds")
+	@SaCheckPermission(TbWalletTopdown.PERMISSION_CODE_DEL)
+	public AjaxJson deleteByIds(){
+		List<Long> ids = SoMap.getRequestSoMap().getListByComma("ids", long.class); 
+		int line = SP.publicMapper.deleteByIds(TbWalletTopdown.TABLE_NAME, ids);
+		return AjaxJson.getByLine(line);
+	}
+	
+	/** 改 */  
+	@RequestMapping("update")
+	@SaCheckPermission(TbWalletTopdown.PERMISSION_CODE_EDIT)
+	public AjaxJson update(TbWalletTopdown t){
+		tbWalletTopdownService.update(t);
+		return AjaxJson.getSuccess();
+	}
+
+	/** 查 - 根据id */  
+	@RequestMapping("getById")
+		@SaCheckPermission(TbWalletTopdown.PERMISSION_CODE)
+	public AjaxJson getById(Long id){
+		TbWalletTopdown t = tbWalletTopdownService.getById(id);
+		return AjaxJson.getSuccessData(t);
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	@RequestMapping("getList")
+		@SaCheckPermission(TbWalletTopdown.PERMISSION_CODE)
+	public AjaxJson getList() { 
+		SoMap so = SoMap.getRequestSoMap();
+		List<WalletTopdownVo> list = tbWalletTopdownService.getList(so.startPage());
+		return AjaxJson.getPageData(so.getDataCount(), list);
+	}
+	
+	
+	
+	/** 改 - 删除状态(0=禁用,1=启用) */  
+	@RequestMapping("updateDeleteStatus")
+	@SaCheckPermission(TbWalletTopdown.PERMISSION_CODE_EDIT)
+	public AjaxJson updateDeleteStatus(Long id, Integer value){
+		int line = SP.publicMapper.updateColumnById(TbWalletTopdown.TABLE_NAME, "delete_status", value, id);
+		return AjaxJson.getByLine(line);
+	}
+
+
+}

+ 29 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownMapper.java

@@ -0,0 +1,29 @@
+package com.pj.tb_wallet_topdown;
+
+import java.util.List;
+import com.pj.tb_wallet_topdown.vo.WalletTopdownVo;
+import org.apache.ibatis.annotations.Mapper;
+import com.pj.utils.so.*;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.springframework.stereotype.Repository;
+
+/**
+ * Mapper: tb_wallet_topdown -- 服务点提现记录
+ * @author plj 
+ */
+
+@Mapper
+@Repository
+public interface TbWalletTopdownMapper extends BaseMapper <TbWalletTopdown> {
+
+
+
+	/**
+	 * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+	 * @param so 参数集合 
+	 * @return 数据列表 
+	 */
+	List<WalletTopdownVo> getList(SoMap so);
+
+
+}

+ 72 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownMapper.xml

@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.tb_wallet_topdown.TbWalletTopdownMapper">
+
+
+
+
+	<!-- ================================== 查询相关 ================================== -->
+	<!-- select id, people_id, mchid, out_trade_no, transaction_id, amount, topdown_time, create_time, create_by, create_name, update_time, update_by, update_name, delete_status from tb_wallet_topdown  -->
+	
+	<!-- 通用映射:自动模式 -->
+	<resultMap id="model" autoMapping="true" type="com.pj.tb_wallet_topdown.vo.WalletTopdownVo"></resultMap>
+	
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select w.*,p.name as peopleName
+		from tb_wallet_topdown as w
+		left join tb_people as p on w.people_id = p.id
+	</sql>
+
+	
+	<!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+			<if test=' this.has("id") '> and w.id = #{id} </if>
+			<if test=' this.has("peopleId") '> and w.people_id = #{peopleId} </if>
+			<if test=' this.has("mchid") '> and w.mchid = #{mchid} </if>
+			<if test=' this.has("outTradeNo") '> and w.out_trade_no = #{outTradeNo} </if>
+			<if test=' this.has("transactionId") '> and w.transaction_id = #{transactionId} </if>
+			<if test=' this.has("goodsName") '> and w.goods_name = #{goodsName} </if>
+			<if test=' this.has("amount") '> and w.amount = #{amount} </if>
+			<if test=' this.has("topdownTime") '> and w.topdown_time = #{topdownTime} </if>
+			<if test=' this.has("createTime") '> and w.create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and w.create_by = #{createBy} </if>
+			<if test=' this.has("createName") '> and w.create_name = #{createName} </if>
+			<if test=' this.has("updateTime") '> and w.update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and w.update_by = #{updateBy} </if>
+			<if test=' this.has("updateName") '> and w.update_name = #{updateName} </if>
+			<if test=' this.has("payStatus") '> and w.pay_status = #{payStatus} </if>
+		</where>
+		order by
+		<choose>
+			<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> people_id desc </when>
+			<when test='sortType == 3'> mchid desc </when>
+			<when test='sortType == 4'> out_trade_no desc </when>
+			<when test='sortType == 5'> transaction_id desc </when>
+			<when test='sortType == 6'> goods_name desc </when>
+			<when test='sortType == 7'> amount desc </when>
+			<when test='sortType == 8'> topdown_time desc </when>
+			<when test='sortType == 9'> create_time desc </when>
+			<when test='sortType == 10'> create_by desc </when>
+			<when test='sortType == 11'> create_name desc </when>
+			<when test='sortType == 12'> update_time desc </when>
+			<when test='sortType == 13'> update_by desc </when>
+			<when test='sortType == 14'> update_name desc </when>
+			<when test='sortType == 15'> pay_status desc </when>
+			<otherwise> topdown_time desc </otherwise>
+		</choose>
+	</select>
+	
+	
+	
+	
+	
+	
+	
+	
+	
+
+</mapper>

+ 55 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/TbWalletTopdownService.java

@@ -0,0 +1,55 @@
+package com.pj.tb_wallet_topdown;
+
+import java.util.List;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.transaction.annotation.Transactional;
+import com.pj.tb_wallet_topdown.vo.WalletTopdownVo;
+/**
+ * Service: tb_wallet_topdown -- 服务点提现记录
+ * @author plj 
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+public class TbWalletTopdownService extends ServiceImpl<TbWalletTopdownMapper, TbWalletTopdown> implements IService<TbWalletTopdown>{
+
+	/** 底层 Mapper 对象 */
+	@Autowired
+	TbWalletTopdownMapper tbWalletTopdownMapper;
+
+	/** 增 */
+	void add(TbWalletTopdown t){
+		save(t);
+	}
+
+	/** 删 */
+	void delete(Long id){
+		removeById(id);
+	}
+
+	/** 改 */
+	void update(TbWalletTopdown t){
+		updateById(t);
+
+	}
+
+	/** 查 */
+	TbWalletTopdown getById(Long id){
+		List<WalletTopdownVo> listObj=tbWalletTopdownMapper.getList(new SoMap().set("id",id));
+		if(listObj!=null && listObj.size()>0) {
+			return listObj.get(0);
+		}else {
+			return  null;
+		}
+	}
+
+	/** 查集合 - 根据条件(参数为空时代表忽略指定条件) */  
+	List<WalletTopdownVo> getList(SoMap so) { 
+		return tbWalletTopdownMapper.getList(so);	
+	}
+	
+
+}

+ 17 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topdown/vo/WalletTopdownVo.java

@@ -0,0 +1,17 @@
+package com.pj.tb_wallet_topdown.vo;
+
+import com.pj.tb_wallet_topdown.TbWalletTopdown;
+import lombok.Data;
+
+/**
+ * Model: tb_wallet_topdown -- 服务点提现记录
+ * @author plj
+ */
+@Data
+public class WalletTopdownVo extends TbWalletTopdown {
+
+    /**
+     * 边民姓名
+     */
+    private String peopleName;
+}

+ 143 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopup.java

@@ -0,0 +1,143 @@
+package com.pj.tb_wallet_topup;
+
+import java.io.Serializable;
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import lombok.EqualsAndHashCode;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * Model: tb_wallet_topup -- 服务点充值记录
+ * @author plj 
+ */
+@Data
+@Accessors(chain = true)
+@TableName(TbWalletTopup.TABLE_NAME)
+@EqualsAndHashCode(callSuper = false)
+public class TbWalletTopup extends Model<TbWalletTopup> implements Serializable {
+
+	// ---------- 模块常量 ----------
+	/**
+	 * 序列化版本id 
+	 */
+	private static final long serialVersionUID = 1L;	
+	/**
+	 * 此模块对应的表名 
+	 */
+	public static final String TABLE_NAME = "tb_wallet_topup";	
+	/**
+	 * 此模块对应的权限码 
+	 */
+	public static final String PERMISSION_CODE = "tb-wallet-topup";
+	public static final String PERMISSION_CODE_ADD = "tb-wallet-topup-add";
+	public static final String PERMISSION_CODE_EDIT = "tb-wallet-topup-edit";
+	public static final String PERMISSION_CODE_DEL = "tb-wallet-topup-del";
+
+
+
+
+	// ---------- 表中字段 ----------
+	/**
+	 * 主键 
+	 */
+	@TableId(type = IdType.AUTO)
+	private Long id;	
+
+	/**
+	 * 边民id 
+	 */
+	private String peopleId;	
+
+	/**
+	 * 商户号 
+	 */
+	private String mchid;	
+
+	/**
+	 * 商户系统内部订单号 
+	 */
+	private String outTradeNo;	
+
+	/**
+	 * 微信支付系统生成的订单号 
+	 */
+	private String transactionId;
+
+	/**
+	 * 商品名称
+	 */
+	private String goodsName;
+	/**
+	 * 充值金额 
+	 */
+	private Integer amount;
+
+	private Integer beforeAmount;
+
+	private Integer afterAmount;
+
+
+	/**
+	 * 已扣除数量
+	 */
+	private Integer cutCount;
+
+	/**
+	 * 充值时间 
+	 */
+	private Date topupTime;
+
+	/**
+	 * 创建时间 
+	 */
+	private Date createTime;
+
+	/**
+	 * 创建人编号 
+	 */
+	private String createBy;	
+
+	/**
+	 * 创建人名称 
+	 */
+	private String createName;	
+
+	/**
+	 * 更新时间 
+	 */
+	private Date updateTime;
+
+	/**
+	 * 更新人编号 
+	 */
+	private String updateBy;	
+
+	/**
+	 * 更新人名称 
+	 */
+	private String updateName;
+
+	private String prepayid;
+	/**
+	 * 支付的用户openid
+	 */
+	private String openid;
+
+	private String successTime;
+
+	/**
+	 * 支付状态(0=未支付,1=支付中,2=已支付,3=取消)
+	 */
+	private Integer payStatus;
+
+	private Integer refundStatus;
+
+	private Integer refundCount;
+
+
+
+}

+ 73 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupController.java

@@ -0,0 +1,73 @@
+package com.pj.tb_wallet_topup;
+
+import java.util.Date;
+import java.util.List;
+
+import com.github.binarywang.wxpay.bean.coupon.*;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
+import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
+import com.github.binarywang.wxpay.bean.request.*;
+import com.github.binarywang.wxpay.bean.result.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.pj.tb_wallet_topup.vo.ValletTopupVo;
+import com.pj.utils.so.SoMap;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+
+import com.pj.utils.sg.*;
+import com.pj.project4sp.SP;
+
+import com.pj.current.satoken.StpUserUtil;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+
+
+/**
+ * Controller: tb_wallet_topup -- 服务点充值记录
+ *
+ * @author plj
+ */
+@RestController
+@RequestMapping("/TbWalletTopup/")
+public class TbWalletTopupController {
+
+    /**
+     * 底层 Service 对象
+     */
+    @Autowired
+    TbWalletTopupService tbWalletTopupService;
+
+
+    /**
+     * 查 - 根据id
+     */
+    @RequestMapping("getById")
+    @SaCheckPermission(TbWalletTopup.PERMISSION_CODE)
+    public AjaxJson getById(Long id) {
+        ValletTopupVo t = tbWalletTopupService.getById(id);
+        return AjaxJson.getSuccessData(t);
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    @RequestMapping("getList")
+    @SaCheckPermission(TbWalletTopup.PERMISSION_CODE)
+    public AjaxJson getList() {
+        SoMap so = SoMap.getRequestSoMap();
+        List<ValletTopupVo> list = tbWalletTopupService.getList(so.startPage());
+        return AjaxJson.getPageData(so.getDataCount(), list);
+    }
+    @RequestMapping("getSum")
+    @SaCheckPermission(TbWalletTopup.PERMISSION_CODE)
+    public AjaxJson getSum() {
+        Integer sum= tbWalletTopupService.getSum();
+        return AjaxJson.getSuccessData(sum);
+    }
+
+
+}

+ 51 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupMapper.java

@@ -0,0 +1,51 @@
+package com.pj.tb_wallet_topup;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.pj.tb_order.TbOrder;
+import com.pj.tb_wallet_topup.vo.ValletTopupVo;
+
+import org.apache.ibatis.annotations.Mapper;
+
+import com.pj.utils.so.*;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+import java.util.List;
+
+/**
+ * Mapper: tb_wallet_topup -- 服务点充值记录
+ *
+ * @author plj
+ */
+
+@Mapper
+@Repository
+public interface TbWalletTopupMapper extends BaseMapper<TbWalletTopup> {
+
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     *
+     * @param so 参数集合
+     * @return 数据列表
+     */
+    List<ValletTopupVo> getList(SoMap so);
+
+
+    default TbWalletTopup findByOutTradeNo(String outTradeNo) {
+        QueryWrapper<TbWalletTopup> ew = new QueryWrapper<>();
+        ew.lambda().eq(TbWalletTopup::getOutTradeNo, outTradeNo);
+        return selectOne(ew);
+    }
+
+    default TbWalletTopup getByPrePayId(String prePayId) {
+        QueryWrapper<TbWalletTopup> ew = new QueryWrapper<>();
+        ew.lambda().eq(TbWalletTopup::getPrepayid, prePayId);
+        return selectOne(ew);
+    }
+
+    void cancelTopup(@Param("outTradeNo") String outTradeNo);
+
+    Integer getSum();
+}

+ 70 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupMapper.xml

@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.pj.tb_wallet_topup.TbWalletTopupMapper">
+
+
+
+
+	<!-- ================================== 查询相关 ================================== -->
+	<!-- select id, people_id, mchid, out_trade_no, transaction_id, amount, topup_time, create_time, create_by, create_name, update_time, update_by, update_name, delete_status from tb_wallet_topup  -->
+	
+	<!-- 通用映射:自动模式 -->
+	<resultMap id="model" autoMapping="true" type="com.pj.tb_wallet_topup.vo.ValletTopupVo"></resultMap>
+	
+	<!-- 公共查询sql片段 -->
+	<sql id="select_sql">
+		select w.*,p.name as peopleName
+		from tb_wallet_topup as w
+		left join tb_people as p on w.people_id = p.id
+	</sql>
+    <delete id="cancelTopup">
+		update tb_wallet_topup set pay_status=3 where out_trade_no=#{outTradeNo}
+	</delete>
+
+
+    <!-- 查集合 - 根据条件(参数为空时代表忽略指定条件) [G] -->
+	<select id="getList" resultMap="model">
+		<include refid="select_sql"></include>
+		<where>
+			<if test=' this.has("id") '> and w.id = #{id} </if>
+			<if test=' this.has("peopleId") '> and w.people_id = #{peopleId} </if>
+			<if test=' this.has("mchid") '> and w.mchid = #{mchid} </if>
+			<if test=' this.has("outTradeNo") '> and w.out_trade_no = #{outTradeNo} </if>
+			<if test=' this.has("transactionId") '> and w.transaction_id = #{transactionId} </if>
+			<if test=' this.has("goodsName") '> and w.goods_name = #{goodsName} </if>
+			<if test=' this.has("amount") '> and w.amount = #{amount} </if>
+			<if test=' this.has("topupTime") '> and w.topup_time = #{topupTime} </if>
+			<if test=' this.has("createTime") '> and w.create_time = #{createTime} </if>
+			<if test=' this.has("createBy") '> and w.create_by = #{createBy} </if>
+			<if test=' this.has("createName") '> and w.create_name = #{createName} </if>
+			<if test=' this.has("updateTime") '> and w.update_time = #{updateTime} </if>
+			<if test=' this.has("updateBy") '> and w.update_by = #{updateBy} </if>
+			<if test=' this.has("updateName") '> and w.update_name = #{updateName} </if>
+			<if test=' this.has("payStatus") '> and w.pay_status = #{payStatus} </if>
+		</where>
+		order by
+		<choose>
+			<when test='sortType == 1'> id desc </when>
+			<when test='sortType == 2'> people_id desc </when>
+			<when test='sortType == 3'> mchid desc </when>
+			<when test='sortType == 4'> out_trade_no desc </when>
+			<when test='sortType == 5'> transaction_id desc </when>
+			<when test='sortType == 6'> goods_name desc </when>
+			<when test='sortType == 7'> amount desc </when>
+			<when test='sortType == 8'> topup_time desc </when>
+			<when test='sortType == 9'> create_time desc </when>
+			<when test='sortType == 10'> create_by desc </when>
+			<when test='sortType == 11'> create_name desc </when>
+			<when test='sortType == 12'> update_time desc </when>
+			<when test='sortType == 13'> update_by desc </when>
+			<when test='sortType == 14'> update_name desc </when>
+			<when test='sortType == 15'> pay_status desc </when>
+			<otherwise> topup_time desc </otherwise>
+		</choose>
+	</select>
+	<select id="getSum" resultType="java.lang.Integer">
+		select sum(amount) from tb_wallet_topup where pay_status =2
+	</select>
+
+
+</mapper>

+ 196 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/TbWalletTopupService.java

@@ -0,0 +1,196 @@
+package com.pj.tb_wallet_topup;
+
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.pj.project4sp.spcfg.SpCfgUtil;
+import com.pj.tb_order.TbOrder;
+import com.pj.tb_people.TbPeopleService;
+import com.pj.tb_wallet_record.TbWalletRecord;
+import com.pj.tb_wallet_record.WxPayProperties;
+import com.pj.tb_wallet_record.vo.NotifyBO;
+import com.pj.tb_wallet_topup.vo.ValletTopupVo;
+import com.pj.utils.cache.RedisUtil;
+import com.pj.utils.so.SoMap;
+import com.wechat.pay.java.service.payments.app.AppServiceExtension;
+import com.wechat.pay.java.service.payments.app.model.CloseOrderRequest;
+import com.wechat.pay.java.service.payments.app.model.QueryOrderByIdRequest;
+import com.wechat.pay.java.service.payments.app.model.QueryOrderByOutTradeNoRequest;
+import com.wechat.pay.java.service.payments.model.Transaction;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.Resource;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * Service: tb_wallet_topup -- 服务点充值记录
+ *
+ * @author plj
+ */
+@Service
+@Transactional(rollbackFor = Exception.class)
+@Slf4j
+public class TbWalletTopupService extends ServiceImpl<TbWalletTopupMapper, TbWalletTopup> implements IService<TbWalletTopup> {
+
+    /**
+     * 底层 Mapper 对象
+     */
+    @Autowired
+    TbWalletTopupMapper tbWalletTopupMapper;
+    @Resource
+    private AppServiceExtension appServiceExtension;
+    @Autowired
+    WxPayProperties wxPayProperties;
+    @Resource
+    private TbPeopleService tbPeopleService;
+
+    /**
+     * 增
+     */
+    void add(TbWalletTopup t) {
+        save(t);
+    }
+
+    /**
+     * 删
+     */
+    void delete(Long id) {
+        removeById(id);
+    }
+
+    /**
+     * 改
+     */
+    void update(TbWalletTopup t) {
+        updateById(t);
+    }
+
+    /**
+     * 查
+     */
+    ValletTopupVo getById(Long id) {
+        List<ValletTopupVo> listObj = tbWalletTopupMapper.getList(new SoMap().set("id", id));
+        if (listObj != null && listObj.size() > 0) {
+            return listObj.get(0);
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * 查集合 - 根据条件(参数为空时代表忽略指定条件)
+     */
+    List<ValletTopupVo> getList(SoMap so) {
+        return tbWalletTopupMapper.getList(so);
+    }
+
+
+    public void WxNotify(NotifyBO notifyBO) {
+        String orderStatus = notifyBO.getTradeStatus();
+        if (!"SUCCESS".equals(orderStatus) && !"FINISH".equals(orderStatus)) {
+            log.error("支付订单回调失败:{}", JSONUtil.toJsonStr(notifyBO));
+            return;
+        }
+        String outTradeNo = notifyBO.getOutTradeNo();
+        if (StrUtil.isNotEmpty(RedisUtil.get(outTradeNo))) {
+            log.error("========订单已处理==========:{}", outTradeNo);
+            return;
+        }
+        RedisUtil.setByMINUTES(outTradeNo, DateUtil.now(), 10);
+        TbWalletTopup tbWalletTopup = tbWalletTopupMapper.findByOutTradeNo(outTradeNo);
+        if (tbWalletTopup == null) {
+            log.error("========订单不存在==========:{}", outTradeNo);
+            return;
+        }
+    }
+
+    public void handlerTopup(String outTradeNoStr) {
+        String key = wxPayProperties.getMchId() + "-" + wxPayProperties.getAppId();
+        long now = System.currentTimeMillis() / 1000 - 30 * 60;
+        String outTradeNo = StrUtil.subBefore(outTradeNoStr, "-", true);
+        String timeStr = StrUtil.subAfter(outTradeNoStr, "-", true);
+        if (StrUtil.isEmpty(timeStr) || now > Long.parseLong(timeStr)) {
+            RedisUtil.forListRemove(key, outTradeNoStr);
+            tbWalletTopupMapper.cancelTopup(outTradeNo);
+            return;
+        }
+
+        QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
+        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+        request.setMchid(wxPayProperties.getMchId());
+        request.setOutTradeNo(outTradeNo);
+        // 调用接口
+        Transaction transaction = appServiceExtension.queryOrderByOutTradeNo(request);
+        if (transaction.getTradeState().name().equals("SUCCESS")) {
+            RedisUtil.forListRemove(key, outTradeNoStr);
+            TbWalletTopup tbWalletTopup = tbWalletTopupMapper.findByOutTradeNo(outTradeNo);
+            tbWalletTopup.setPayStatus(2).setSuccessTime(transaction.getSuccessTime())
+                    .setTransactionId(transaction.getTransactionId())
+                    .setOpenid(transaction.getPayer().getOpenid())
+                    .setUpdateTime(new Date());
+            this.updateById(tbWalletTopup);
+            tbPeopleService.updatePeopleWallet(tbWalletTopup.getPeopleId(), tbWalletTopup.getAmount());
+        }
+        log.info("Transaction:{}", transaction);
+    }
+
+    /**
+     * 关闭订单
+     */
+    public void closeOrder(String outTradeNo) {
+        CloseOrderRequest request = new CloseOrderRequest();
+        // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义
+        request.setMchid(wxPayProperties.getMchId());
+        request.setOutTradeNo(outTradeNo);
+        // 调用接口
+        appServiceExtension.closeOrder(request);
+    }
+
+    public TbWalletTopup getByPrePayId(String prePayId) {
+        return tbWalletTopupMapper.getByPrePayId(prePayId);
+    }
+
+    /**
+     * 减去扣除点数
+     *
+     * @param peopleId
+     */
+    public void subAmount(Long peopleId) {
+        TbWalletTopup tbWalletTopup = getTheFirstRecord(peopleId);
+        if (tbWalletTopup != null) {
+            tbWalletTopup.setCutCount(tbWalletTopup.getCutCount() + SpCfgUtil.getTradeNum());
+            updateById(tbWalletTopup);
+        }
+    }
+
+    private TbWalletTopup getTheFirstRecord(Long peopleId) {
+        LambdaQueryWrapper<TbWalletTopup> ew = new LambdaQueryWrapper<>();
+        ew.eq(TbWalletTopup::getPeopleId, peopleId)
+                .eq(TbWalletTopup::getPayStatus, 2)
+                .apply("amount > cut_count + refund_count")
+                .orderByAsc(TbWalletTopup::getCreateTime);
+        List<TbWalletTopup> list = list(ew);
+        return list.isEmpty() ? null : list.get(0);
+    }
+
+    public Integer getSum() {
+        return tbWalletTopupMapper.getSum();
+    }
+
+    public List<TbWalletTopup> findRefundList(Long peopleId) {
+        LambdaQueryWrapper<TbWalletTopup> ew = new LambdaQueryWrapper<>();
+        ew.eq(TbWalletTopup::getPeopleId, peopleId)
+                .eq(TbWalletTopup::getPayStatus, 2)
+                .apply("amount > cut_count + refund_count")
+                .orderByAsc(TbWalletTopup::getCreateTime);
+        return list(ew);
+    }
+}

+ 51 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/WalletTopupAppController.java

@@ -0,0 +1,51 @@
+package com.pj.tb_wallet_topup;
+
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import com.pj.current.satoken.StpAPPUserUtil;
+import com.pj.project4sp.SP;
+import com.pj.tb_wallet_record.TbWalletRecord;
+import com.pj.tb_wallet_topup.vo.ValletTopupVo;
+import com.pj.utils.sg.AjaxJson;
+import com.pj.utils.so.SoMap;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+
+/**
+ * Controller: tb_wallet_topup -- 服务点充值记录
+ * @author plj 
+ */
+@RestController
+@RequestMapping("/app/TbWalletTopup/")
+public class WalletTopupAppController {
+
+	/** 底层 Service 对象 */
+	@Autowired
+	TbWalletTopupService tbWalletTopupService;
+
+	/** 查 - 根据id */  
+	@RequestMapping("getByPrePayId")
+	public AjaxJson getByPrePayId(String prePayId){
+		if (!StpAPPUserUtil.isLogin()){
+			return AjaxJson.getError("用户未登录");
+		}
+		TbWalletTopup t = tbWalletTopupService.getByPrePayId(prePayId);
+		return AjaxJson.getSuccessData(t);
+	}
+	/**
+	 * 查 - 根据id
+	 */
+	@RequestMapping("getById")
+	public AjaxJson getById(Long id) {
+		if (!StpAPPUserUtil.isLogin()){
+			return AjaxJson.getError("用户未登录");
+		}
+		TbWalletTopup t = tbWalletTopupService.getById(id);
+		return AjaxJson.getSuccessData(t);
+	}
+
+
+}

+ 352 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/WxPayController.java

@@ -0,0 +1,352 @@
+package com.pj.tb_wallet_topup;
+
+import com.github.binarywang.wxpay.bean.coupon.*;
+import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
+import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
+import com.github.binarywang.wxpay.bean.request.*;
+import com.github.binarywang.wxpay.bean.result.*;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import java.util.Date;
+
+
+/**
+ * @author plj
+ */
+@Slf4j
+@RestController
+@RequestMapping("/WxPay/")
+public class WxPayController {
+  @Autowired
+  private WxPayService wxService;
+
+  /**
+   * <pre>
+   * 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
+   * 该接口提供所有微信支付订单的查询,商户可以通过查询订单接口主动查询订单状态,完成下一步的业务逻辑。
+   * 需要调用查询接口的情况:
+   * ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
+   * ◆ 调用支付接口后,返回系统错误或未知交易状态情况;
+   * ◆ 调用被扫支付API,返回USERPAYING的状态;
+   * ◆ 调用关单或撤销接口API之前,需确认支付状态;
+   * 接口地址:https://api.mch.weixin.qq.com/pay/orderquery
+   * </pre>
+   *
+   * @param transactionId 微信订单号
+   * @param outTradeNo    商户系统内部的订单号,当没提供transactionId时需要传这个。
+   */
+  @ApiOperation(value = "查询订单")
+  @GetMapping("/queryOrder")
+  public WxPayOrderQueryResult queryOrder(@RequestParam(required = false) String transactionId,
+                                          @RequestParam(required = false) String outTradeNo)
+    throws WxPayException {
+    return this.wxService.queryOrder(transactionId, outTradeNo);
+  }
+
+  @ApiOperation(value = "查询订单")
+  @PostMapping("/queryOrder")
+  public WxPayOrderQueryResult queryOrder(@RequestBody WxPayOrderQueryRequest wxPayOrderQueryRequest) throws WxPayException {
+    return this.wxService.queryOrder(wxPayOrderQueryRequest);
+  }
+
+  /**
+   * <pre>
+   * 关闭订单
+   * 应用场景
+   * 以下情况需要调用关单接口:
+   * 1. 商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;
+   * 2. 系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
+   * 注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。
+   * 接口地址:https://api.mch.weixin.qq.com/pay/closeorder
+   * 是否需要证书:   不需要。
+   * </pre>
+   *
+   * @param outTradeNo 商户系统内部的订单号
+   */
+  @ApiOperation(value = "关闭订单")
+  @GetMapping("/closeOrder/{outTradeNo}")
+  public WxPayOrderCloseResult closeOrder(@PathVariable String outTradeNo) throws WxPayException {
+    return this.wxService.closeOrder(outTradeNo);
+  }
+
+  @ApiOperation(value = "关闭订单")
+  @PostMapping("/closeOrder")
+  public WxPayOrderCloseResult closeOrder(@RequestBody WxPayOrderCloseRequest wxPayOrderCloseRequest) throws WxPayException {
+    return this.wxService.closeOrder(wxPayOrderCloseRequest);
+  }
+
+  /**
+   * 调用统一下单接口,并组装生成支付所需参数对象.
+   *
+   * @param request 统一下单请求参数
+   * @param <T>     请使用{@link com.github.binarywang.wxpay.bean.order}包下的类
+   * @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
+   */
+  @ApiOperation(value = "统一下单,并组装所需支付参数")
+  @PostMapping("/createOrder")
+  public <T> T createOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
+    log.error(this.wxService.getConfig().toString());
+    return this.wxService.createOrder(request);
+  }
+
+  /**
+   * 统一下单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
+   * 在发起微信支付前,需要调用统一下单接口,获取"预支付交易会话标识"
+   * 接口地址:https://api.mch.weixin.qq.com/pay/unifiedorder
+   *
+   * @param request 请求对象,注意一些参数如appid、mchid等不用设置,方法内会自动从配置对象中获取到(前提是对应配置中已经设置)
+   */
+  @ApiOperation(value = "原生的统一下单接口")
+  @PostMapping("/unifiedOrder")
+  public WxPayUnifiedOrderResult unifiedOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
+    return this.wxService.unifiedOrder(request);
+  }
+
+  /**
+   * <pre>
+   * 微信支付-申请退款
+   * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
+   * 接口链接:https://api.mch.weixin.qq.com/secapi/pay/refund
+   * </pre>
+   *
+   * @param request 请求对象
+   * @return 退款操作结果
+   */
+  @ApiOperation(value = "退款")
+  @PostMapping("/refund")
+  public WxPayRefundResult refund(@RequestBody WxPayRefundRequest request) throws WxPayException {
+    return this.wxService.refund(request);
+  }
+
+  /**
+   * <pre>
+   * 微信支付-查询退款
+   * 应用场景:
+   *  提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,
+   *  银行卡支付的退款3个工作日后重新查询退款状态。
+   * 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
+   * 接口链接:https://api.mch.weixin.qq.com/pay/refundquery
+   * </pre>
+   * 以下四个参数四选一
+   *
+   * @param transactionId 微信订单号
+   * @param outTradeNo    商户订单号
+   * @param outRefundNo   商户退款单号
+   * @param refundId      微信退款单号
+   * @return 退款信息
+   */
+  @ApiOperation(value = "退款查询")
+  @GetMapping("/refundQuery")
+  public WxPayRefundQueryResult refundQuery(@RequestParam(required = false) String transactionId,
+                                            @RequestParam(required = false) String outTradeNo,
+                                            @RequestParam(required = false) String outRefundNo,
+                                            @RequestParam(required = false) String refundId)
+    throws WxPayException {
+    return this.wxService.refundQuery(transactionId, outTradeNo, outRefundNo, refundId);
+  }
+
+  @ApiOperation(value = "退款查询")
+  @PostMapping("/refundQuery")
+  public WxPayRefundQueryResult refundQuery(@RequestBody WxPayRefundQueryRequest wxPayRefundQueryRequest) throws WxPayException {
+    return this.wxService.refundQuery(wxPayRefundQueryRequest);
+  }
+
+  @ApiOperation(value = "支付回调通知处理")
+  @PostMapping("/notify/order")
+  public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
+    final WxPayOrderNotifyResult notifyResult = this.wxService.parseOrderNotifyResult(xmlData);
+    // TODO 根据自己业务场景需要构造返回对象
+    return WxPayNotifyResponse.success("成功");
+  }
+
+  @ApiOperation(value = "退款回调通知处理")
+  @PostMapping("/notify/refund")
+  public String parseRefundNotifyResult(@RequestBody String xmlData) throws WxPayException {
+    final WxPayRefundNotifyResult result = this.wxService.parseRefundNotifyResult(xmlData);
+    // TODO 根据自己业务场景需要构造返回对象
+    return WxPayNotifyResponse.success("成功");
+  }
+
+  @ApiOperation(value = "扫码支付回调通知处理")
+  @PostMapping("/notify/scanpay")
+  public String parseScanPayNotifyResult(String xmlData) throws WxPayException {
+    final WxScanPayNotifyResult result = this.wxService.parseScanPayNotifyResult(xmlData);
+    // TODO 根据自己业务场景需要构造返回对象
+    return WxPayNotifyResponse.success("成功");
+  }
+
+  /**
+   * 发送微信红包给个人用户
+   * <pre>
+   * 文档详见:
+   * 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
+   *  接口地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
+   * 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
+   *  接口地址:https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack
+   * </pre>
+   *
+   * @param request 请求对象
+   */
+  @ApiOperation(value = "发送红包")
+  @PostMapping("/sendRedpack")
+  public WxPaySendRedpackResult sendRedpack(@RequestBody WxPaySendRedpackRequest request) throws WxPayException {
+    return this.wxService.getRedpackService().sendRedpack(request);
+  }
+
+  /**
+   * <pre>
+   *   查询红包记录
+   *   用于商户对已发放的红包进行查询红包的具体信息,可支持普通红包和裂变包。
+   *   请求Url	https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
+   *   是否需要证书	是(证书及使用说明详见商户证书)
+   *   请求方式	POST
+   * </pre>
+   *
+   * @param mchBillNo 商户发放红包的商户订单号,比如10000098201411111234567890
+   */
+  @ApiOperation(value = "查询红包")
+  @GetMapping("/queryRedpack/{mchBillNo}")
+  public WxPayRedpackQueryResult queryRedpack(@PathVariable String mchBillNo) throws WxPayException {
+    return this.wxService.getRedpackService().queryRedpack(mchBillNo);
+  }
+
+
+  /**
+   * <pre>
+   * 扫码支付模式一生成二维码的方法
+   * 二维码中的内容为链接,形式为:
+   * weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
+   * 其中XXXXX为商户需要填写的内容,商户将该链接生成二维码,如需要打印发布二维码,需要采用此格式。商户可调用第三方库生成二维码图片。
+   * 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
+   * </pre>
+   *
+   * @param productId 产品Id
+   * @return 生成的二维码URL连接
+   */
+  public String createScanPayQrcodeMode1(String productId) {
+    return this.wxService.createScanPayQrcodeMode1(productId);
+  }
+
+  /**
+   * <pre>
+   * 交易保障
+   * 应用场景:
+   *  商户在调用微信支付提供的相关接口时,会得到微信支付返回的相关信息以及获得整个接口的响应时间。
+   *  为提高整体的服务水平,协助商户一起提高服务质量,微信支付提供了相关接口调用耗时和返回信息的主动上报接口,
+   *  微信支付可以根据商户侧上报的数据进一步优化网络部署,完善服务监控,和商户更好的协作为用户提供更好的业务体验。
+   * 接口地址: https://api.mch.weixin.qq.com/payitil/report
+   * 是否需要证书:不需要
+   * </pre>
+   */
+  @ApiOperation(value = "提交交易保障数据")
+  @PostMapping("/report")
+  public void report(@RequestBody WxPayReportRequest request) throws WxPayException {
+    this.wxService.report(request);
+  }
+
+  /**
+   * <pre>
+   * 下载对账单
+   * 商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。
+   * 注意:
+   * 1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED;
+   * 2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取;
+   * 3、对账单中涉及金额的字段单位为“元”。
+   * 4、对账单接口只能下载三个月以内的账单。
+   * 接口链接:https://api.mch.weixin.qq.com/pay/downloadbill
+   * 详情请见: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单</a>
+   * </pre>
+   *
+   * @param billDate   对账单日期 bill_date	下载对账单的日期,格式:20140603
+   * @param billType   账单类型	bill_type	ALL,返回当日所有订单信息,默认值,SUCCESS,返回当日成功支付的订单,REFUND,返回当日退款订单
+   * @param tarType    压缩账单	tar_type	非必传参数,固定值:GZIP,返回格式为.gzip的压缩包账单。不传则默认为数据流形式。
+   * @param deviceInfo 设备号	device_info	非必传参数,终端设备号
+   * @return 保存到本地的临时文件
+   */
+  @ApiOperation(value = "下载对账单")
+  @GetMapping("/downloadBill/{billDate}/{billType}/{tarType}/{deviceInfo}")
+  public WxPayBillResult downloadBill(@PathVariable String billDate, @PathVariable String billType,
+                                      @PathVariable String tarType, @PathVariable String deviceInfo) throws WxPayException {
+    return this.wxService.downloadBill(billDate, billType, tarType, deviceInfo);
+  }
+
+  @ApiOperation(value = "下载对账单")
+  @PostMapping("/downloadBill")
+  public WxPayBillResult downloadBill(WxPayDownloadBillRequest wxPayDownloadBillRequest) throws WxPayException {
+    return this.wxService.downloadBill(wxPayDownloadBillRequest);
+  }
+
+  /**
+   * <pre>
+   * 提交刷卡支付
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
+   * 应用场景:
+   * 收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付。
+   * 提醒1:提交支付请求后微信会同步返回支付结果。当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】,查询支付实际交易结果;当返回结果为“USERPAYING”时,商户系统可设置间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒);
+   * 提醒2:在调用查询接口返回后,如果交易状况不明晰,请调用【撤销订单API】,此时如果交易失败则关闭订单,该单不能再支付成功;如果交易成功,则将扣款退回到用户账户。当撤销无返回或错误时,请再次调用。注意:请勿扣款后立即调用【撤销订单API】,建议至少15秒后再调用。撤销订单API需要双向证书。
+   * 接口地址:   https://api.mch.weixin.qq.com/pay/micropay
+   * 是否需要证书:不需要。
+   * </pre>
+   */
+  @ApiOperation(value = "提交刷卡支付")
+  @PostMapping("/micropay")
+  public WxPayMicropayResult micropay(@RequestBody WxPayMicropayRequest request) throws WxPayException {
+    return this.wxService.micropay(request);
+  }
+
+  /**
+   * <pre>
+   * 撤销订单API
+   * 文档地址:https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
+   * 应用场景:
+   *  支付交易返回失败或支付系统超时,调用该接口撤销交易。如果此订单用户支付失败,微信支付系统会将此订单关闭;如果用户支付成功,微信支付系统会将此订单资金退还给用户。
+   *  注意:7天以内的交易单可调用撤销,其他正常支付的单如需实现相同功能请调用申请退款API。提交支付交易后调用【查询订单API】,没有明确的支付结果再调用【撤销订单API】。
+   *  调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口。
+   *  接口链接 :https://api.mch.weixin.qq.com/secapi/pay/reverse
+   *  是否需要证书:请求需要双向证书。
+   * </pre>
+   */
+  @ApiOperation(value = "撤销订单")
+  @PostMapping("/reverseOrder")
+  public WxPayOrderReverseResult reverseOrder(@RequestBody WxPayOrderReverseRequest request) throws WxPayException {
+    return this.wxService.reverseOrder(request);
+  }
+
+  @ApiOperation(value = "获取沙箱环境签名key")
+  @GetMapping("/getSandboxSignKey")
+  public String getSandboxSignKey() throws WxPayException {
+    return this.wxService.getSandboxSignKey();
+  }
+
+  @ApiOperation(value = "发放代金券")
+  @PostMapping("/sendCoupon")
+  public WxPayCouponSendResult sendCoupon(@RequestBody WxPayCouponSendRequest request) throws WxPayException {
+    return this.wxService.sendCoupon(request);
+  }
+
+  @ApiOperation(value = "查询代金券批次")
+  @PostMapping("/queryCouponStock")
+  public WxPayCouponStockQueryResult queryCouponStock(@RequestBody WxPayCouponStockQueryRequest request) throws WxPayException {
+    return this.wxService.queryCouponStock(request);
+  }
+
+  @ApiOperation(value = "查询代金券信息")
+  @PostMapping("/queryCouponInfo")
+  public WxPayCouponInfoQueryResult queryCouponInfo(@RequestBody WxPayCouponInfoQueryRequest request) throws WxPayException {
+    return this.wxService.queryCouponInfo(request);
+  }
+
+  @ApiOperation(value = "拉取订单评价数据")
+  @PostMapping("/queryComment")
+  public String queryComment(Date beginDate, Date endDate, Integer offset, Integer limit) throws WxPayException {
+    return this.wxService.queryComment(beginDate, endDate, offset, limit);
+  }
+
+}
+

+ 33 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/task/QueryPayTask.java

@@ -0,0 +1,33 @@
+package com.pj.tb_wallet_topup.task;
+
+import cn.hutool.core.util.StrUtil;
+import com.pj.tb_wallet_record.TbWalletRecordService;
+import com.pj.tb_wallet_record.WxPayProperties;
+import com.pj.tb_wallet_topup.TbWalletTopupService;
+import com.pj.utils.cache.RedisUtil;
+import com.wechat.pay.java.service.payments.app.AppServiceExtension;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+@Component
+@Slf4j
+public class QueryPayTask {
+    @Resource
+    private WxPayProperties wxPayProperties;
+    @Resource
+    private TbWalletTopupService tbWalletTopupService;
+
+    @Scheduled(cron = "0/5 * * * * ?")  //每3秒执行一次
+    public void query() {
+        String key = wxPayProperties.getMchId() + "-" + wxPayProperties.getAppId();
+        List<Object> list = RedisUtil.forListGet(key);
+        for (Object tradeObj : list) {
+            String tradeNo = tradeObj.toString();
+            tbWalletTopupService.handlerTopup(tradeNo);
+        }
+    }
+}

+ 19 - 0
sp-service/level-one-server/src/main/java/com/pj/tb_wallet_topup/vo/ValletTopupVo.java

@@ -0,0 +1,19 @@
+package com.pj.tb_wallet_topup.vo;
+
+import com.pj.tb_wallet_topup.TbWalletTopup;
+import lombok.Data;
+
+/**
+ * Model: tb_wallet_topup -- 铺位
+ * @author plj
+ */
+@Data
+public class ValletTopupVo extends TbWalletTopup {
+
+
+    /**
+     * 边民姓名
+     */
+    private String peopleName;
+
+}

+ 6 - 0
sp-service/sp-admin/pom.xml

@@ -31,6 +31,12 @@
             <artifactId>thumbnailator</artifactId>
             <version>0.4.8</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.arcsoft.face</groupId>
+            <artifactId>arcsoft-sdk-face</artifactId>
+            <version>3.0.0.0</version>
+        </dependency>
     </dependencies>