| | |
| | | throw new RuntimeException("根据id获取用户失败"); |
| | | } |
| | | |
| | | @Override |
| | | @Override |
| | | public List<AppUser> getAppUserAll() { |
| | | log.error("获取所有用户失败:{}", cause.getMessage()); |
| | | throw new RuntimeException("获取所有用户失败"); } |
| | | |
| | | @Override |
| | | public R<Void> editAppUserById(AppUser appUser) { |
| | | log.error("编辑用户信息失败:{}", cause.getMessage()); |
| | | return R.fail("编辑用户信息失败"); |
| | |
| | | */ |
| | | @PostMapping("/app-user/getAppUserById") |
| | | AppUser getAppUserById(@RequestParam("id") Long id); |
| | | /** |
| | | * 查询所有用户 |
| | | * @return |
| | | */ |
| | | @PostMapping("/app-user/getAppUserAll") |
| | | List<AppUser> getAppUserAll(); |
| | | |
| | | /** |
| | | * 根据id编辑用户 |
New file |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author luodangjia |
| | | * @since 2024-11-20 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_integral_pay") |
| | | @ApiModel(value="IntegralPay对象", description="积分充值记录") |
| | | public class IntegralPay implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Integer id; |
| | | |
| | | @ApiModelProperty(value = "系统用户id") |
| | | @TableField("user_id") |
| | | private Long userId; |
| | | @ApiModelProperty(value = "积分数量") |
| | | @TableField("integral_count") |
| | | private Integer integralCount; |
| | | @ApiModelProperty(value = "支付金额") |
| | | @TableField("amount") |
| | | private BigDecimal amount; |
| | | @ApiModelProperty(value = "支付时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("pay_time") |
| | | private LocalDateTime payTime; |
| | | @ApiModelProperty(value = "订单号") |
| | | @TableField("code") |
| | | private String code; |
| | | @ApiModelProperty(value = "流水号") |
| | | @TableField("order_number") |
| | | private String orderNumber; |
| | | @ApiModelProperty(value = "支付状态 1待支付 2已支付") |
| | | @TableField("pay_status") |
| | | private Integer payStatus; |
| | | @ApiModelProperty(value = "删除标识(0=否,1=是)") |
| | | @TableField("del_flag") |
| | | private Integer delFlag; |
| | | @ApiModelProperty(value = "添加时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("create_time") |
| | | private LocalDateTime createTime; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author luodangjia |
| | | * @since 2024-11-20 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_integral_record") |
| | | @ApiModel(value="IntegralRecord对象", description="积分明细") |
| | | public class IntegralRecord implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Integer id; |
| | | @ApiModelProperty(value = "站点id") |
| | | @TableField("site_id") |
| | | private Integer siteId; |
| | | @ApiModelProperty(value = "用户id") |
| | | @TableField("app_user_id") |
| | | private Long appUserId; |
| | | @ApiModelProperty(value = "支付记录id") |
| | | @TableField("pay_id") |
| | | private Integer payId; |
| | | @ApiModelProperty(value = "积分类型 1充值积分 2充电订单扣除") |
| | | @TableField("integral_type") |
| | | private Integer integralType; |
| | | @ApiModelProperty(value = "积分数量") |
| | | @TableField("integral_count") |
| | | private Integer integralCount; |
| | | @ApiModelProperty(value = "删除标识(0=否,1=是)") |
| | | @TableField("del_flag") |
| | | private Integer delFlag; |
| | | @ApiModelProperty(value = "添加时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("create_time") |
| | | private LocalDateTime createTime; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author luodangjia |
| | | * @since 2024-11-20 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_service_pay") |
| | | @ApiModel(value="ServicePay对象", description="服务费充值记录") |
| | | public class ServicePay implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Integer id; |
| | | |
| | | @ApiModelProperty(value = "系统用户id") |
| | | @TableField("user_id") |
| | | private Long userId; |
| | | |
| | | @ApiModelProperty(value = "支付金额") |
| | | @TableField("amount") |
| | | private BigDecimal amount; |
| | | @ApiModelProperty(value = "支付时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("pay_time") |
| | | private LocalDateTime payTime; |
| | | |
| | | @ApiModelProperty(value = "到期时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("end_time") |
| | | private LocalDateTime endTime; |
| | | |
| | | @ApiModelProperty(value = "订单号") |
| | | @TableField("code") |
| | | private String code; |
| | | @ApiModelProperty(value = "流水号") |
| | | @TableField("order_number") |
| | | private String orderNumber; |
| | | @ApiModelProperty(value = "支付状态 1待支付 2已支付") |
| | | @TableField("pay_status") |
| | | private Integer payStatus; |
| | | @ApiModelProperty(value = "支付方式 1微信 2支付宝 当前只有微信") |
| | | @TableField("pay_type") |
| | | private Integer payType; |
| | | @ApiModelProperty(value = "删除标识(0=否,1=是)") |
| | | @TableField("del_flag") |
| | | private Integer delFlag; |
| | | @ApiModelProperty(value = "添加时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | @TableField("create_time") |
| | | private LocalDateTime createTime; |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.api.domain; |
| | | |
| | | import com.baomidou.mybatisplus.annotation.IdType; |
| | | import com.baomidou.mybatisplus.annotation.TableField; |
| | | import com.baomidou.mybatisplus.annotation.TableId; |
| | | import com.baomidou.mybatisplus.annotation.TableName; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import lombok.EqualsAndHashCode; |
| | | |
| | | import java.io.Serializable; |
| | | |
| | | /** |
| | | * <p> |
| | | * |
| | | * </p> |
| | | * |
| | | * @author 无关风月 |
| | | * @since 2024-08-06 |
| | | */ |
| | | @Data |
| | | @EqualsAndHashCode(callSuper = false) |
| | | @TableName("t_integral_rule") |
| | | @ApiModel(value="TIntegralRule对象", description="") |
| | | public class TIntegralRule implements Serializable { |
| | | |
| | | private static final long serialVersionUID = 1L; |
| | | |
| | | @ApiModelProperty(value = "主键") |
| | | @TableId(value = "id", type = IdType.AUTO) |
| | | private Integer id; |
| | | |
| | | @ApiModelProperty(value = "充电得积分{\"num1\":1}") |
| | | @TableField("charge_credit") |
| | | private String chargeCredit; |
| | | |
| | | @ApiModelProperty(value = "好评得积分{\"num1\":1}") |
| | | @TableField("credit") |
| | | private String credit; |
| | | |
| | | @ApiModelProperty(value = "添加车辆得积分{\"num1\":1,\"num2\":1,\"num3\":1,\"num4\":1}") |
| | | @TableField("add_vehicles_earns_points") |
| | | private String addVehiclesEarnsPoints; |
| | | @ApiModelProperty(value = "积分规则说明") |
| | | @TableField("content") |
| | | private String content; |
| | | @ApiModelProperty(value = "站点id") |
| | | @TableField("site_id") |
| | | private Integer siteId; |
| | | } |
| | |
| | | import com.ruoyi.common.core.web.domain.BaseEntity; |
| | | import com.ruoyi.common.core.xss.Xss; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | import org.apache.commons.lang3.builder.ToStringBuilder; |
| | | import org.apache.commons.lang3.builder.ToStringStyle; |
| | | import org.springframework.format.annotation.DateTimeFormat; |
| | |
| | | import java.util.Date; |
| | | import java.util.List; |
| | | |
| | | @Data |
| | | /** |
| | | * 用户对象 sys_user |
| | | * |
| | |
| | | @Excel(name = "部门编号", type = Type.IMPORT) |
| | | @TableField("dept_id") |
| | | private Long deptId; |
| | | // 站点id |
| | | @TableField("site_id") |
| | | private Integer siteId; |
| | | // 积分 |
| | | @TableField("integral") |
| | | private Integer integral; |
| | | |
| | | /** 用户账号 */ |
| | | @Excel(name = "登录名称") |
| | |
| | | spring: |
| | | profiles: |
| | | # 环境配置 |
| | | # active: dev |
| | | active: prod |
| | | active: dev |
| | | # active: prod |
| | | application: |
| | | # 应用名称 |
| | | name: ruoyi-auth |
| | |
| | | server: |
| | | port: 8080 |
| | | port: 8084 |
| | | tomcat: |
| | | basedir: /mnt/tomcat |
| | | # Spring |
| | |
| | | allow-circular-references: true |
| | | profiles: |
| | | # 环境配置 |
| | | # active: dev |
| | | active: prod |
| | | active: dev |
| | | # active: prod |
| | | --- |
| | | spring: |
| | | config: |
| | |
| | | allow-bean-definition-overriding: true |
| | | profiles: |
| | | # 环境配置 |
| | | # active: dev |
| | | active: prod |
| | | active: dev |
| | | # active: prod |
| | | --- |
| | | spring: |
| | | config: |
| | |
| | | select u.user_id, u.dept_id, u.user_name, u.nick_name, u.email, u.avatar, u.phonenumber, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.role_type, u.create_by, u.create_time, u.remark, |
| | | d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status, |
| | | r.role_id, r.role_name, r.role_key, r.data_scope, r.status as role_status ,u.role_type as roleType,u.objectId AS objectId |
| | | ,u.site_id as siteId |
| | | from sys_user u |
| | | left join sys_dept d on u.dept_id = d.dept_id |
| | | left join sys_user_role ur on u.user_id = ur.user_id |
| | |
| | | <if test="remark != null and remark != ''">remark,</if> |
| | | <if test="objectId != null and objectId != ''">objectId,</if> |
| | | <if test="appUserId != null and appUserId != ''">app_user_id,</if> |
| | | <if test="siteId != null and siteId != ''">site_id,</if> |
| | | create_time |
| | | )values( |
| | | <if test="userId != null and userId != ''">#{userId},</if> |
| | |
| | | <if test="remark != null and remark != ''">#{remark},</if> |
| | | <if test="objectId != null and objectId != ''">#{objectId},</if> |
| | | <if test="appUserId != null and appUserId != ''">#{appUserId},</if> |
| | | <if test="siteId != null and siteId != ''">#{siteId},</if> |
| | | sysdate() |
| | | ) |
| | | </insert> |
| | |
| | | <if test="forbiddenRemark != null">forbidden_remark = #{forbiddenRemark},</if> |
| | | <if test="roleType != null">role_type = #{roleType},</if> |
| | | <if test="objectId != null">objectId = #{objectId},</if> |
| | | <if test="siteId != null">site_id = #{siteId},</if> |
| | | <if test="integral != null">integral = #{integral},</if> |
| | | update_time = sysdate() |
| | | </set> |
| | | where user_id = #{userId} |
| | |
| | | </description> |
| | | |
| | | <dependencies> |
| | | <dependency> |
| | | <groupId>org.springframework.boot</groupId> |
| | | <artifactId>spring-boot-starter-test</artifactId> |
| | | <scope>test</scope> |
| | | </dependency> |
| | | |
| | | <!--lombok--> |
| | | <dependency> |
| | |
| | | System.out.println("根据id获取用户:"+id); |
| | | return appUserService.getById(id); |
| | | } |
| | | // 获取所有用户 |
| | | @PostMapping("/getAppUserAll") |
| | | public List<AppUser> getAppUserAll() { |
| | | return appUserService.list(); |
| | | } |
| | | |
| | | @PostMapping("/getBaseUserById") |
| | | public R<Map<String, Object>> getBaseUserById(@RequestParam("id") Long id) { |
| | |
| | | allow-circular-references: true |
| | | profiles: |
| | | # 环境配置 |
| | | # active: dev |
| | | active: prod |
| | | active: dev |
| | | # active: prod |
| | | --- |
| | | spring: |
| | | config: |
| | |
| | | allow-circular-references: true |
| | | profiles: |
| | | # 环境配置 |
| | | # active: dev |
| | | active: prod |
| | | active: dev |
| | | # active: prod |
| | | --- |
| | | spring: |
| | | config: |
| | |
| | | <artifactId>dom4j</artifactId> |
| | | <version>1.6.1</version> |
| | | </dependency> |
| | | <dependency> |
| | | <groupId>org.springframework</groupId> |
| | | <artifactId>spring-test</artifactId> |
| | | </dependency> |
| | | </dependencies> |
| | | |
| | | <build> |
| | |
| | | @GetMapping("/getAgreement/{type}") |
| | | @ApiOperation(value = "获取协议", tags = {"小程序-登录注册"}) |
| | | @ApiImplicitParams({ |
| | | @ApiImplicitParam(value = "类型(1=用户协议,2=隐私协议,4=注销协议,5门店提现免责声明)", name = "type", required = true, dataType = "int"), |
| | | @ApiImplicitParam(value = "类型(1=用户协议,2=隐私协议,4=注销协议,5门店提现免责声明,6=积分规则说明)", name = "type", required = true, dataType = "int"), |
| | | }) |
| | | public R<String> getAgreement(@PathVariable("type") Integer type){ |
| | | Agreement one = agreementService.getOne(new LambdaQueryWrapper<Agreement>().eq(Agreement::getType, type)); |
New file |
| | |
| | | package com.ruoyi.other.controller; |
| | | |
| | | import com.alibaba.fastjson.JSONObject; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.other.api.domain.IntegralPay; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.service.TIntegralPayService; |
| | | import com.ruoyi.other.service.TIntegralRecordService; |
| | | import com.ruoyi.other.service.TIntegralRuleService; |
| | | import com.ruoyi.other.util.MyQrCodeUtil; |
| | | import com.ruoyi.other.util.ObsUploadUtil; |
| | | import com.ruoyi.other.util.QRCodeUtil; |
| | | import com.ruoyi.other.util.UUIDUtil; |
| | | import com.ruoyi.other.util.payment.wx.WechatPayService; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import com.ruoyi.other.vo.IntegralVO; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.core.io.ByteArrayResource; |
| | | import org.springframework.mock.web.MockMultipartFile; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.imageio.ImageIO; |
| | | import java.awt.image.BufferedImage; |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Date; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * <p> |
| | | * 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author 无关风月 |
| | | * @since 2024-08-06 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/integral") |
| | | public class TIntegralController { |
| | | |
| | | @Autowired |
| | | private TIntegralRuleService integralRuleService; |
| | | @Autowired |
| | | private TIntegralRecordService integralRecordService; |
| | | @Autowired |
| | | private TIntegralPayService integralPayService; |
| | | |
| | | @Autowired |
| | | private TokenService tokenService; |
| | | @Resource |
| | | private SysUserClient sysUserClient; |
| | | @Resource |
| | | private WechatPayService wechatPayService; |
| | | @PostMapping("/integralPageList") |
| | | @ApiOperation(tags = {"2.0-积分钱包"},value = "积分钱包") |
| | | public R<IntegralVO> integralPageList(@RequestBody IntegralListQuery query) { |
| | | Long userid = tokenService.getLoginUser().getUserid(); |
| | | R<SysUser> sysUser = sysUserClient.getSysUser(userid); |
| | | query.setSiteId(sysUser.getData().getSiteId()); |
| | | Integer integral = sysUser.getData().getIntegral(); |
| | | IntegralVO integralVO = new IntegralVO(); |
| | | PageInfo<IntegralListVO> integralListVOPageInfo = integralRecordService.integralPageList(query); |
| | | integralVO.setIntegralList(integralListVOPageInfo); |
| | | integralVO.setIntegral(integral); |
| | | return R.ok(integralVO); |
| | | } |
| | | @PostMapping("/queryPayStatus") |
| | | @ApiOperation(tags = {"2.0-积分钱包"},value = "查询支付结果 true成功 false失败") |
| | | public R<Boolean> integralPageList(@RequestParam("code") String code) throws Exception { |
| | | Map<String, String> resMap = wechatPayService.queryOrder(code); |
| | | if("SUCCESS".equals(resMap.get("return_code"))){ |
| | | return R.ok(true); |
| | | }else{ |
| | | return R.ok(false); |
| | | } |
| | | } |
| | | |
| | | @PostMapping("/nativePay") |
| | | @ApiOperation(tags = {"2.0-积分钱包"},value = "获取支付二维码") |
| | | public R nativePay(@RequestParam("amount") String amount) throws Exception { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
| | | String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); |
| | | Map<String, String> res = wechatPayService.unifiedOrder(code, amount, "积分充值", "/other/wx/integralCallback"); |
| | | Long userid = tokenService.getLoginUser().getUserid(); |
| | | R<SysUser> sysUser = sysUserClient.getSysUser(userid); |
| | | SysUser data = sysUser.getData(); |
| | | // 生成待支付记录 |
| | | IntegralPay integralPay = new IntegralPay(); |
| | | integralPay.setUserId(data.getUserId()); |
| | | TIntegralRule one = integralRuleService.lambdaQuery().eq(TIntegralRule::getSiteId, 0).one(); |
| | | if (one==null){ |
| | | return R.fail("获取支付失败,平台未设置充值积分比例"); |
| | | } |
| | | String chargeCredit = one.getChargeCredit(); |
| | | JSONObject jsonObject = JSONObject.parseObject(chargeCredit); |
| | | Integer num1 = jsonObject.getInteger("num1"); |
| | | BigDecimal bigDecimal = new BigDecimal(amount); |
| | | // 向上取整 比如5.1 当作6 5.9也当作6 |
| | | integralPay.setIntegralCount(bigDecimal.divide(new BigDecimal(num1), RoundingMode.UP).intValue()); |
| | | int i = bigDecimal.multiply(new BigDecimal(num1)).intValue(); |
| | | integralPay.setIntegralCount(i); |
| | | integralPay.setAmount(new BigDecimal(amount)); |
| | | integralPay.setCode(code); |
| | | integralPay.setPayStatus(1); |
| | | integralPay.setDelFlag(0); |
| | | integralPay.setCreateTime(LocalDateTime.now()); |
| | | integralPayService.save(integralPay); |
| | | String codeUrl = res.get("code_url"); |
| | | MyQrCodeUtil.createCodeToFile(codeUrl); |
| | | BufferedImage blueImage = QRCodeUtil.createImage(codeUrl); |
| | | MultipartFile blueFile = convert(blueImage, new Date().getTime() + UUIDUtil.getRandomCode(3) + ".PNG"); |
| | | String s = ObsUploadUtil.obsUpload(blueFile); |
| | | System.err.println(s); |
| | | return R.ok(s); |
| | | } |
| | | public static MultipartFile convert(BufferedImage bufferedImage, String fileName) throws IOException { |
| | | // 将 BufferedImage 转换为字节数组 |
| | | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| | | ImageIO.write(bufferedImage, "png", baos); |
| | | byte[] bytes = baos.toByteArray(); |
| | | |
| | | // 创建 ByteArrayResource |
| | | ByteArrayResource resource = new ByteArrayResource(bytes); |
| | | |
| | | // 创建 MockMultipartFile |
| | | MockMultipartFile multipartFile = new MockMultipartFile( |
| | | "file", |
| | | fileName, |
| | | "image/png", |
| | | resource.getInputStream() |
| | | ); |
| | | |
| | | return multipartFile; |
| | | } |
| | | @GetMapping("/getSet") |
| | | @ApiOperation(tags = {"2.0-积分管理"},value = "获取积分设置") |
| | | public R<TIntegralRule> getSet() { |
| | | Long userid = tokenService.getLoginUser().getUserid(); |
| | | SysUser data = sysUserClient.getSysUser(userid).getData(); |
| | | |
| | | if (data!=null&&data.getSiteId()!=null){ |
| | | if (data.getRoleType()==1){ |
| | | // 平台 |
| | | TIntegralRule res = integralRuleService.lambdaQuery().eq(TIntegralRule::getSiteId, 0).one(); |
| | | return R.ok(res); |
| | | }else{ |
| | | TIntegralRule res = integralRuleService.lambdaQuery().eq(TIntegralRule::getSiteId, data.getSiteId()).one(); |
| | | return R.ok(res); |
| | | } |
| | | }else { |
| | | return R.ok(new TIntegralRule()); |
| | | } |
| | | } |
| | | |
| | | @PostMapping("/saveSet") |
| | | @ApiOperation(tags = {"2.0-积分管理"},value = "保存积分设置") |
| | | @Log(title = "【积分管理】保存积分设置", businessType = BusinessType.INSERT) |
| | | public R saveSet(@RequestBody TIntegralRule dto) { |
| | | Long userid = tokenService.getLoginUser().getUserid(); |
| | | SysUser data = sysUserClient.getSysUser(userid).getData(); |
| | | TIntegralRule one; |
| | | if (data.getRoleType()==1){ |
| | | one = integralRuleService.lambdaQuery().eq(TIntegralRule::getSiteId, 0).one(); |
| | | }else{ |
| | | one = integralRuleService.lambdaQuery().eq(TIntegralRule::getSiteId, data.getSiteId()).one(); |
| | | } |
| | | if (one!=null){ |
| | | dto.setId(one.getId()); |
| | | integralRuleService.saveOrUpdate(dto); |
| | | }else{ |
| | | integralRuleService.saveOrUpdate(dto); |
| | | } |
| | | return R.ok(); |
| | | } |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.other.controller; |
| | | |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.log.annotation.Log; |
| | | import com.ruoyi.common.log.enums.BusinessType; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.other.api.domain.ServicePay; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.query.ServiceListQuery; |
| | | import com.ruoyi.other.service.TIntegralRecordService; |
| | | import com.ruoyi.other.service.TIntegralRuleService; |
| | | import com.ruoyi.other.service.TServicePayService; |
| | | import com.ruoyi.other.util.MyQrCodeUtil; |
| | | import com.ruoyi.other.util.ObsUploadUtil; |
| | | import com.ruoyi.other.util.QRCodeUtil; |
| | | import com.ruoyi.other.util.UUIDUtil; |
| | | import com.ruoyi.other.util.payment.wx.WechatPayService; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import com.ruoyi.other.vo.IntegralVO; |
| | | import com.ruoyi.other.vo.ServiceListVO; |
| | | import com.ruoyi.other.vo.ServiceVO; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.core.io.ByteArrayResource; |
| | | import org.springframework.mock.web.MockMultipartFile; |
| | | import org.springframework.web.bind.annotation.*; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.imageio.ImageIO; |
| | | import java.awt.image.BufferedImage; |
| | | import java.io.IOException; |
| | | import java.math.BigDecimal; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Date; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * <p> |
| | | * 前端控制器 |
| | | * </p> |
| | | * |
| | | * @author 无关风月 |
| | | * @since 2024-08-06 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/integralRule") |
| | | public class TServiceController { |
| | | |
| | | @Autowired |
| | | private TIntegralRuleService integralRuleService; |
| | | @Autowired |
| | | private TIntegralRecordService integralRecordService; |
| | | |
| | | @Autowired |
| | | private TokenService tokenService; |
| | | @Resource |
| | | private SysUserClient sysUserClient; |
| | | @Resource |
| | | private WechatPayService wechatPayService; |
| | | @Resource |
| | | private TServicePayService servicePayService; |
| | | @PostMapping("/servicePageList") |
| | | @ApiOperation(tags = {"2.0-服务费管理"},value = "服务费管理") |
| | | public R<ServiceVO> integralPageList(@RequestBody ServiceListQuery query) { |
| | | Long userid = tokenService.getLoginUser().getUserid(); |
| | | R<SysUser> sysUser = sysUserClient.getSysUser(userid); |
| | | query.setUserId(userid); |
| | | ServiceVO serviceVO = new ServiceVO(); |
| | | PageInfo<ServiceListVO> serviceListVOPageInfo = servicePayService.servicePageList(query); |
| | | serviceVO.setServiceList(serviceListVOPageInfo); |
| | | ServicePay servicePayBefore = servicePayService.lambdaQuery() |
| | | .eq(ServicePay::getUserId, userid) |
| | | .eq(ServicePay::getPayStatus,2) |
| | | .orderByDesc(ServicePay::getCreateTime) |
| | | .last("limit 1") |
| | | .one(); |
| | | if (servicePayBefore==null){ |
| | | serviceVO.setStatus(1); |
| | | } else if (servicePayBefore.getEndTime().isBefore(LocalDateTime.now())) { |
| | | serviceVO.setStatus(2); |
| | | }else{ |
| | | serviceVO.setStatus(3); |
| | | } |
| | | if (servicePayBefore!=null){ |
| | | serviceVO.setEndTime(servicePayBefore.getEndTime()); |
| | | } |
| | | return R.ok(serviceVO); |
| | | } |
| | | @PostMapping("/queryPayStatus") |
| | | @ApiOperation(tags = {"2.0-服务费"},value = "查询支付结果 true成功 false失败") |
| | | public R<Boolean> integralPageList(@RequestParam("code") String code) throws Exception { |
| | | Map<String, String> resMap = wechatPayService.queryOrder(code); |
| | | if("SUCCESS".equals(resMap.get("return_code"))){ |
| | | return R.ok(true); |
| | | }else{ |
| | | return R.ok(false); |
| | | } |
| | | } |
| | | @PostMapping("/nativePay") |
| | | @ApiOperation(tags = {"2.0-服务费"},value = "获取支付二维码") |
| | | public R nativePay(@RequestParam("amount") String amount) throws Exception { |
| | | Long userid = tokenService.getLoginUser().getUserid(); |
| | | R<SysUser> sysUser = sysUserClient.getSysUser(userid); |
| | | SysUser data = sysUser.getData(); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
| | | String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); |
| | | Map<String,String> res = wechatPayService.unifiedOrder(code, amount, "服务费缴纳", "/other/wx/serviceCallback"); |
| | | ServicePay servicePay = new ServicePay(); |
| | | servicePay.setUserId(data.getUserId()); |
| | | servicePay.setAmount(new BigDecimal( amount)); |
| | | servicePay.setCode(code); |
| | | servicePay.setPayStatus(1); |
| | | servicePay.setPayType(1); |
| | | servicePay.setDelFlag(0); |
| | | servicePay.setCreateTime(LocalDateTime.now()); |
| | | servicePayService.save(servicePay); |
| | | String codeUrl = res.get("code_url"); |
| | | MyQrCodeUtil.createCodeToFile(codeUrl); |
| | | BufferedImage blueImage = QRCodeUtil.createImage(codeUrl); |
| | | MultipartFile blueFile = convert(blueImage, new Date().getTime() + UUIDUtil.getRandomCode(3) + ".PNG"); |
| | | String s = ObsUploadUtil.obsUpload(blueFile); |
| | | System.err.println(s); |
| | | return R.ok(s); |
| | | } |
| | | public static MultipartFile convert(BufferedImage bufferedImage, String fileName) throws IOException { |
| | | // 将 BufferedImage 转换为字节数组 |
| | | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| | | ImageIO.write(bufferedImage, "png", baos); |
| | | byte[] bytes = baos.toByteArray(); |
| | | |
| | | // 创建 ByteArrayResource |
| | | ByteArrayResource resource = new ByteArrayResource(bytes); |
| | | |
| | | // 创建 MockMultipartFile |
| | | MockMultipartFile multipartFile = new MockMultipartFile( |
| | | "file", |
| | | fileName, |
| | | "image/png", |
| | | resource.getInputStream() |
| | | ); |
| | | |
| | | return multipartFile; |
| | | } |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.other.controller; |
| | | |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.common.security.service.TokenService; |
| | | import com.ruoyi.other.api.domain.IntegralPay; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.api.domain.ServicePay; |
| | | import com.ruoyi.other.query.ServiceListQuery; |
| | | import com.ruoyi.other.service.TIntegralPayService; |
| | | import com.ruoyi.other.service.TIntegralRecordService; |
| | | import com.ruoyi.other.service.TIntegralRuleService; |
| | | import com.ruoyi.other.service.TServicePayService; |
| | | import com.ruoyi.other.util.UUIDUtil; |
| | | import com.ruoyi.other.util.payment.wx.PayResult; |
| | | import com.ruoyi.other.util.payment.wx.WechatPayService; |
| | | import com.ruoyi.other.vo.ServiceListVO; |
| | | import com.ruoyi.other.vo.ServiceVO; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import com.ruoyi.system.api.feignClient.SysUserClient; |
| | | import io.swagger.annotations.ApiOperation; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.web.bind.annotation.*; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.IOException; |
| | | import java.io.PrintWriter; |
| | | import java.text.SimpleDateFormat; |
| | | import java.time.LocalDateTime; |
| | | import java.util.Date; |
| | | import java.util.Map; |
| | | |
| | | /** |
| | | * <p> |
| | | * 微信回调 |
| | | * </p> |
| | | * |
| | | * @author 无关风月 |
| | | * @since 2024-08-06 |
| | | */ |
| | | @RestController |
| | | @RequestMapping("/wx") |
| | | public class WXCallBackController { |
| | | |
| | | @Autowired |
| | | private TIntegralRuleService integralRuleService; |
| | | @Autowired |
| | | private TIntegralRecordService integralRecordService; |
| | | @Autowired |
| | | private TIntegralPayService integralPayService; |
| | | |
| | | @Autowired |
| | | private TokenService tokenService; |
| | | @Resource |
| | | private SysUserClient sysUserClient; |
| | | @Resource |
| | | private WechatPayService wechatPayService; |
| | | @Resource |
| | | private TServicePayService servicePayService; |
| | | @ResponseBody |
| | | @PostMapping("/integralCallback") |
| | | public void integralCallback(HttpServletRequest request, HttpServletResponse response){ |
| | | System.err.println("积分充值回调"); |
| | | PayResult payResult= null; |
| | | try { |
| | | payResult = wechatPayService.processNotify(request); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | IntegralPay integralPay = integralPayService.lambdaQuery().eq(IntegralPay::getCode, payResult.getOrderNumber()).one(); |
| | | if (integralPay != null && integralPay.getPayStatus() == 1){ |
| | | SysUser data = sysUserClient.getSysUser(integralPay.getUserId()).getData(); |
| | | integralPay.setPayStatus(2); |
| | | integralPay.setPayTime(LocalDateTime.now()); |
| | | integralPay.setOrderNumber(payResult.getTransactionId()); |
| | | integralPayService.updateById(integralPay); |
| | | IntegralRecord integralRecord = new IntegralRecord(); |
| | | integralRecord.setPayId(integralPay.getId()); |
| | | integralRecord.setSiteId(data.getSiteId()); |
| | | integralRecord.setAppUserId(integralPay.getUserId()); |
| | | integralRecord.setIntegralType(1); |
| | | integralRecord.setIntegralCount(integralPay.getIntegralCount()); |
| | | integralRecord.setDelFlag(0); |
| | | integralRecord.setCreateTime(LocalDateTime.now()); |
| | | integralRecordService.save(integralRecord); |
| | | data.setIntegral(data.getIntegral()+integralPay.getIntegralCount()); |
| | | sysUserClient.updateSysUser(data); |
| | | } |
| | | response.setStatus(200); |
| | | PrintWriter out = null; |
| | | try { |
| | | out = response.getWriter(); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | out.println("success"); |
| | | out.flush(); |
| | | out.close(); |
| | | } |
| | | @ResponseBody |
| | | @PostMapping("/serviceCallback") |
| | | public void serviceCallback(HttpServletRequest request, HttpServletResponse response){ |
| | | System.err.println("服务费缴纳回调"); |
| | | PayResult payResult= null; |
| | | try { |
| | | payResult = wechatPayService.processNotify(request); |
| | | } catch (Exception e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | ServicePay servicePay = servicePayService.lambdaQuery().eq(ServicePay::getCode, payResult.getOrderNumber()).one(); |
| | | if (servicePay != null && servicePay.getPayStatus() == 1){ |
| | | servicePay.setPayStatus(2); |
| | | ServicePay servicePayBefore = servicePayService.lambdaQuery() |
| | | .eq(ServicePay::getUserId, servicePay.getUserId()) |
| | | .eq(ServicePay::getPayStatus,2) |
| | | .orderByDesc(ServicePay::getCreateTime) |
| | | .last("limit 1") |
| | | .one(); |
| | | if (servicePayBefore!=null){ |
| | | servicePay.setEndTime(servicePayBefore.getEndTime().plusDays(365)); |
| | | }else{ |
| | | servicePay.setEndTime(LocalDateTime.now().plusDays(365)); |
| | | |
| | | } |
| | | |
| | | servicePay.setPayType(1); |
| | | servicePay.setPayTime(LocalDateTime.now()); |
| | | servicePay.setOrderNumber(payResult.getTransactionId()); |
| | | servicePayService.updateById(servicePay); |
| | | } |
| | | response.setStatus(200); |
| | | PrintWriter out = null; |
| | | try { |
| | | out = response.getWriter(); |
| | | } catch (IOException e) { |
| | | throw new RuntimeException(e); |
| | | } |
| | | out.println("success"); |
| | | out.flush(); |
| | | out.close(); |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.other.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralPay; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:46 |
| | | */ |
| | | public interface IntegralPayMapper extends BaseMapper<IntegralPay> { |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:46 |
| | | */ |
| | | public interface IntegralRecordMapper extends BaseMapper<IntegralRecord> { |
| | | List<IntegralListVO> integralPageList(@Param("query") IntegralListQuery query, |
| | | @Param("pageInfo") PageInfo<IntegralListVO> pageInfo); |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.other.api.domain.Agreement; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:46 |
| | | */ |
| | | public interface IntegralRuleMapper extends BaseMapper<TIntegralRule> { |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.mapper; |
| | | |
| | | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralPay; |
| | | import com.ruoyi.other.api.domain.ServicePay; |
| | | import com.ruoyi.other.query.ServiceListQuery; |
| | | import com.ruoyi.other.vo.ServiceListVO; |
| | | import org.apache.ibatis.annotations.Param; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:46 |
| | | */ |
| | | public interface ServicePayMapper extends BaseMapper<ServicePay> { |
| | | List<ServiceListVO> servicePageList(@Param("query") ServiceListQuery query, @Param("pageInfo") PageInfo<ServiceListVO> pageInfo); |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.query; |
| | | |
| | | import com.ruoyi.common.core.web.page.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "积分明细查询query") |
| | | public class IntegralListQuery extends BasePage { |
| | | @ApiModelProperty("类型 1充值 2扣除 全部不传") |
| | | private Integer type; |
| | | @ApiModelProperty("站点 前端忽略") |
| | | private Integer siteId; |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.query; |
| | | |
| | | import com.ruoyi.common.core.web.page.BasePage; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "服务费缴纳明细查询query") |
| | | public class ServiceListQuery extends BasePage { |
| | | |
| | | @ApiModelProperty("用户id 前端忽略") |
| | | private Long userId; |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralPay; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务类 |
| | | * </p> |
| | | * |
| | | * @author luodangjia |
| | | * @since 2024-11-20 |
| | | */ |
| | | public interface TIntegralPayService extends IService<IntegralPay> { |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务类 |
| | | * </p> |
| | | * |
| | | * @author luodangjia |
| | | * @since 2024-11-20 |
| | | */ |
| | | public interface TIntegralRecordService extends IService<IntegralRecord> { |
| | | |
| | | PageInfo<IntegralListVO> integralPageList(IntegralListQuery query); |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务类 |
| | | * </p> |
| | | * |
| | | * @author luodangjia |
| | | * @since 2024-11-20 |
| | | */ |
| | | public interface TIntegralRuleService extends IService<TIntegralRule> { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.IService; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.api.domain.ServicePay; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.query.ServiceListQuery; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import com.ruoyi.other.vo.ServiceListVO; |
| | | |
| | | /** |
| | | * <p> |
| | | * 服务类 |
| | | * </p> |
| | | * |
| | | * @author luodangjia |
| | | * @since 2024-11-20 |
| | | */ |
| | | public interface TServicePayService extends IService<ServicePay> { |
| | | |
| | | |
| | | PageInfo<ServiceListVO> servicePageList(ServiceListQuery query); |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.feignClient.AppUserClient; |
| | | import com.ruoyi.account.api.model.AppUser; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralPay; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.mapper.IntegralPayMapper; |
| | | import com.ruoyi.other.mapper.IntegralRecordMapper; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.service.TIntegralPayService; |
| | | import com.ruoyi.other.service.TIntegralRecordService; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:48 |
| | | */ |
| | | @Service |
| | | public class IntegralPayServiceImpl extends ServiceImpl<IntegralPayMapper, IntegralPay> implements TIntegralPayService { |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.feignClient.AppUserClient; |
| | | import com.ruoyi.account.api.model.AppUser; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | import com.ruoyi.other.mapper.IntegralRecordMapper; |
| | | import com.ruoyi.other.mapper.IntegralRuleMapper; |
| | | import com.ruoyi.other.query.IntegralListQuery; |
| | | import com.ruoyi.other.service.TIntegralRecordService; |
| | | import com.ruoyi.other.service.TIntegralRuleService; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import com.ruoyi.system.api.domain.SysUser; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:48 |
| | | */ |
| | | @Service |
| | | public class IntegralRecordServiceImpl extends ServiceImpl<IntegralRecordMapper, IntegralRecord> implements TIntegralRecordService { |
| | | @Autowired |
| | | private AppUserClient appUserClient; |
| | | @Override |
| | | public PageInfo<IntegralListVO> integralPageList(IntegralListQuery query) { |
| | | PageInfo<IntegralListVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize()); |
| | | List<IntegralListVO> list = this.baseMapper.integralPageList(query,pageInfo); |
| | | List<AppUser> appUserAll = appUserClient.getAppUserAll(); |
| | | for (IntegralListVO integralListVO : list) { |
| | | if (integralListVO.getAppUserId()!=null){ |
| | | AppUser appUser = appUserAll.stream().filter(e -> e.getId().equals(integralListVO.getAppUserId())) |
| | | .findFirst().orElse(null); |
| | | if (appUser!=null){ |
| | | integralListVO.setAppUserName(appUser.getName()); |
| | | integralListVO.setPhone(appUser.getPhone()); |
| | | } |
| | | } |
| | | } |
| | | pageInfo.setRecords(list); |
| | | return pageInfo; |
| | | } |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.other.api.domain.Agreement; |
| | | import com.ruoyi.other.api.domain.TIntegralRule; |
| | | import com.ruoyi.other.mapper.AgreementMapper; |
| | | import com.ruoyi.other.mapper.IntegralRuleMapper; |
| | | import com.ruoyi.other.service.IAgreementService; |
| | | import com.ruoyi.other.service.TIntegralRuleService; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:48 |
| | | */ |
| | | @Service |
| | | public class IntegralRuleServiceImpl extends ServiceImpl<IntegralRuleMapper, TIntegralRule> implements TIntegralRuleService { |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; |
| | | import com.ruoyi.account.api.model.AppUser; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralPay; |
| | | import com.ruoyi.other.api.domain.ServicePay; |
| | | import com.ruoyi.other.mapper.IntegralPayMapper; |
| | | import com.ruoyi.other.mapper.ServicePayMapper; |
| | | import com.ruoyi.other.query.ServiceListQuery; |
| | | import com.ruoyi.other.service.TIntegralPayService; |
| | | import com.ruoyi.other.service.TServicePayService; |
| | | import com.ruoyi.other.vo.IntegralListVO; |
| | | import com.ruoyi.other.vo.ServiceListVO; |
| | | import org.springframework.stereotype.Service; |
| | | |
| | | import java.util.List; |
| | | |
| | | /** |
| | | * @author zhibing.pu |
| | | * @Date 2024/11/21 10:48 |
| | | */ |
| | | @Service |
| | | public class ServicePayServiceImpl extends ServiceImpl<ServicePayMapper, ServicePay> implements TServicePayService { |
| | | |
| | | @Override |
| | | public PageInfo<ServiceListVO> servicePageList(ServiceListQuery query) { |
| | | PageInfo<ServiceListVO> pageInfo = new PageInfo<>(query.getPageCurr(), query.getPageSize()); |
| | | List<ServiceListVO> list = this.baseMapper.servicePageList(query,pageInfo); |
| | | pageInfo.setRecords(list); |
| | | return pageInfo; |
| | | } |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.util; |
| | | |
| | | import com.baomidou.mybatisplus.core.toolkit.StringUtils; |
| | | import com.google.zxing.BarcodeFormat; |
| | | import com.google.zxing.EncodeHintType; |
| | | import com.google.zxing.MultiFormatWriter; |
| | | import com.google.zxing.WriterException; |
| | | import com.google.zxing.common.BitMatrix; |
| | | import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; |
| | | |
| | | import javax.imageio.ImageIO; |
| | | import java.awt.image.BufferedImage; |
| | | import java.io.OutputStream; |
| | | import java.util.HashMap; |
| | | import java.util.Map; |
| | | |
| | | public class MyQrCodeUtil { |
| | | //CODE_WIDTH:二维码宽度,单位像素 |
| | | private static final int CODE_WIDTH = 400; |
| | | //CODE_HEIGHT:二维码高度,单位像素 |
| | | private static final int CODE_HEIGHT = 400; |
| | | //FRONT_COLOR:二维码前景色,0x000000 表示黑色 |
| | | private static final int FRONT_COLOR = 0x000000; |
| | | //BACKGROUND_COLOR:二维码背景色,0xFFFFFF 表示白色 |
| | | //演示用 16 进制表示,和前端页面 CSS 的取色是一样的,注意前后景颜色应该对比明显,如常见的黑白 |
| | | private static final int BACKGROUND_COLOR = 0xFFFFFF; |
| | | public static BufferedImage createCodeToFile(String content) { |
| | | try { |
| | | content = content.trim(); |
| | | //核心代码-生成二维码 |
| | | BufferedImage bufferedImage = getBufferedImage(content); |
| | | |
| | | return bufferedImage; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | /** |
| | | * 生成二维码并输出到输出流, 通常用于输出到网页上进行显示,输出到网页与输出到磁盘上的文件中,区别在于最后一句 ImageIO.write |
| | | * write(RenderedImage im,String formatName,File output):写到文件中 |
| | | * write(RenderedImage im,String formatName,OutputStream output):输出到输出流中 |
| | | * @param content :二维码内容 |
| | | * @param outputStream :输出流,比如 HttpServletResponse 的 getOutputStream |
| | | */ |
| | | public static void createCodeToOutputStream(String content, OutputStream outputStream) { |
| | | try { |
| | | if (StringUtils.isBlank(content)) { |
| | | return; |
| | | } |
| | | content = content.trim(); |
| | | //核心代码-生成二维码 |
| | | BufferedImage bufferedImage = getBufferedImage(content); |
| | | //区别就是这一句,输出到输出流中,如果第三个参数是 File,则输出到文件中 |
| | | ImageIO.write(bufferedImage, "png", outputStream); |
| | | System.out.println("二维码图片生成到输出流成功..."); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | //核心代码-生成二维码 |
| | | private static BufferedImage getBufferedImage(String content) throws WriterException { |
| | | //com.google.zxing.EncodeHintType:编码提示类型,枚举类型 |
| | | Map<EncodeHintType, Object> hints = new HashMap(); |
| | | //EncodeHintType.CHARACTER_SET:设置字符编码类型 |
| | | hints.put(EncodeHintType.CHARACTER_SET, "UTF-8"); |
| | | //EncodeHintType.ERROR_CORRECTION:设置误差校正 |
| | | //ErrorCorrectionLevel:误差校正等级,L = ~7% correction、M = ~15% correction、Q = ~25% correction、H = ~30% correction |
| | | //不设置时,默认为 L 等级,等级不一样,生成的图案不同,但扫描的结果是一样的 |
| | | hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); |
| | | //EncodeHintType.MARGIN:设置二维码边距,单位像素,值越小,二维码距离四周越近 |
| | | hints.put(EncodeHintType.MARGIN, 1); |
| | | MultiFormatWriter multiFormatWriter = new MultiFormatWriter(); |
| | | BitMatrix bitMatrix = multiFormatWriter.encode(content, BarcodeFormat.QR_CODE, CODE_WIDTH, CODE_HEIGHT, hints); |
| | | BufferedImage bufferedImage = new BufferedImage(CODE_WIDTH, CODE_HEIGHT, BufferedImage.TYPE_INT_BGR); |
| | | for (int x = 0; x < CODE_WIDTH; x++) { |
| | | for (int y = 0; y < CODE_HEIGHT; y++) { |
| | | bufferedImage.setRGB(x, y, bitMatrix.get(x, y) ? FRONT_COLOR : BACKGROUND_COLOR); |
| | | } |
| | | } |
| | | return bufferedImage; |
| | | } |
| | | |
| | | // public static void main(String[] args) { |
| | | // String param = "{\n" + |
| | | // " \"scan_type\": 1,\n" + |
| | | // " \"space_id\": 2,\n" + |
| | | // " \"sutu_id\": 3\n" + |
| | | // "}"; |
| | | // createCodeToFile(param); |
| | | // } |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.util; |
| | | |
| | | import com.obs.services.ObsClient; |
| | | import com.obs.services.model.ObjectMetadata; |
| | | import com.obs.services.model.PutObjectResult; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import java.io.IOException; |
| | | import java.io.InputStream; |
| | | import java.util.UUID; |
| | | |
| | | public class ObsUploadUtil { |
| | | //OBS图片访问域名 |
| | | public static String endPoint = "obs.cn-southwest-2.myhuaweicloud.com"; |
| | | public static String accessKeyId = "F95RSIZQ1B77MGRTPWSU"; |
| | | public static String accessKeySecret = "rMhmXnuDGPwI5ptq0jGCZ6QwaoUDQ5ZJm3RFrZuy"; |
| | | public static String bucketName = "qijishenghuiyuan"; |
| | | public static String oss_domain = "http://qijishenghuiyuan.obs.cn-southwest-2.myhuaweicloud.com/"; |
| | | |
| | | |
| | | // 创建ObsClient实例 |
| | | public static ObsClient obsClient = new ObsClient(accessKeyId, accessKeySecret, endPoint); |
| | | |
| | | public static String obsUpload(MultipartFile file) throws IOException{ |
| | | String fileName = ""; |
| | | if(file!=null && !"".equals(file.getOriginalFilename()) && file.getOriginalFilename()!=null){ |
| | | InputStream content = file.getInputStream();//获得指定文件的输入流 |
| | | ObjectMetadata meta = new ObjectMetadata();// 创建上传Object的Metadata |
| | | meta.setContentLength(file.getSize()); // 必须设置ContentLength |
| | | String originalFilename = file.getOriginalFilename(); |
| | | fileName = UUID.randomUUID().toString().replaceAll("-","") + originalFilename.subSequence(originalFilename.lastIndexOf("."), originalFilename.length()); |
| | | obsClient.putObject(bucketName,"admin/"+fileName,content,meta); |
| | | if(fileName != null && !"".equals(fileName)){ |
| | | System.out.println(fileName); |
| | | fileName = oss_domain+"admin/"+fileName; |
| | | } |
| | | } |
| | | return fileName; |
| | | } |
| | | |
| | | |
| | | |
| | | public static String obsUpload(String suffix, InputStream content){ |
| | | String fileName = UUID.randomUUID().toString().replaceAll("-","") + "." + suffix; |
| | | try { |
| | | PutObjectResult putObjectResult = obsClient.putObject(bucketName, "admin/" + fileName, content); |
| | | String objectUrl = putObjectResult.getObjectUrl(); |
| | | return oss_domain+"admin/"+fileName; |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | | return ""; |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 删除某个Object |
| | | * |
| | | * @param bucketUrl |
| | | * @return |
| | | */ |
| | | public static boolean deleteObject(String bucketUrl) { |
| | | try { |
| | | bucketUrl=bucketUrl.replace(oss_domain+"web",""); |
| | | // 删除Object. |
| | | obsClient.deleteObject(bucketName, bucketUrl); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | return false; |
| | | } finally { |
| | | //ossClient.shutdown(); |
| | | } |
| | | return true; |
| | | } |
| | | |
| | | // public static void createBucket(String bucketName) |
| | | // { |
| | | // //初始化 OSSClient |
| | | //// ossClient = new OssClient(endPoint, accessKeyId, accessKeySecret); |
| | | // |
| | | // // 新建一个Bucket |
| | | // Bucket bucket = ossClient.createBucket(bucketName); |
| | | // System.out.println(bucket.getName()); |
| | | // System.out.println(bucket.getCreationDate()); |
| | | // } |
| | | // |
| | | // public static void main(String[] args) { |
| | | // OssUploadUtil.createBucket("ssfdfsd"); |
| | | // } |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.util; |
| | | |
| | | import com.google.zxing.BarcodeFormat; |
| | | import com.google.zxing.EncodeHintType; |
| | | import com.google.zxing.MultiFormatWriter; |
| | | import com.google.zxing.common.BitMatrix; |
| | | import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; |
| | | |
| | | import java.awt.image.BufferedImage; |
| | | import java.util.Hashtable; |
| | | |
| | | /** |
| | | * @author chengst |
| | | * @date 2019/11/4 |
| | | **/ |
| | | public class QRCodeUtil { |
| | | |
| | | private final static String CHARSET = "utf-8"; |
| | | |
| | | private final static int QRSIZEE = 300; |
| | | |
| | | // 二维码颜色 |
| | | private static final int BLACK = 0xFF000000; |
| | | // 二维码颜色 |
| | | private static final int WHITE = 0xFFFFFFFF; |
| | | |
| | | public static BufferedImage createImage(String content){ |
| | | Hashtable<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>(); |
| | | hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.H); |
| | | hints.put(EncodeHintType.CHARACTER_SET, CHARSET); |
| | | hints.put(EncodeHintType.MARGIN, 1); |
| | | BitMatrix bitMatrix = null; |
| | | try { |
| | | bitMatrix = new MultiFormatWriter().encode(content, BarcodeFormat.QR_CODE, QRSIZEE, QRSIZEE,hints); |
| | | }catch (Exception e){ |
| | | e.printStackTrace(); |
| | | } |
| | | int width = bitMatrix.getWidth(); |
| | | int height = bitMatrix.getHeight(); |
| | | BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); |
| | | |
| | | for (int x = 0; x < width; x++) { |
| | | for (int y = 0; y < height; y++) { |
| | | image.setRGB(x, y, bitMatrix.get(x, y) ? BLACK : WHITE); |
| | | } |
| | | } |
| | | return image; |
| | | } |
| | | } |
| | | |
New file |
| | |
| | | package com.ruoyi.other.util; |
| | | |
| | | |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.UUID; |
| | | |
| | | /** |
| | | * 定义生成随机码的工具类 |
| | | */ |
| | | public class UUIDUtil { |
| | | |
| | | private int i = 1; |
| | | |
| | | |
| | | /** |
| | | * 定义生成原生的UUID随机码 |
| | | * |
| | | * @return |
| | | */ |
| | | public static String getNativeUUID() { |
| | | return UUID.randomUUID().toString(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 生成32位随机码 |
| | | * |
| | | * @return |
| | | */ |
| | | public static String getRandomCode() { |
| | | return UUIDUtil.getNativeUUID().replaceAll("-", ""); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取给定长度的随机码 |
| | | * |
| | | * @param num |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public static String getRandomCode(Integer num) throws Exception { |
| | | String str = null; |
| | | if (0 < num) { |
| | | if (num % 32 > 0) { |
| | | Integer s = num / 32; |
| | | Integer l = num % 32; |
| | | StringBuffer sb = new StringBuffer(); |
| | | for (int i = 0; i < s; i++) { |
| | | sb.append(UUIDUtil.getRandomCode()); |
| | | } |
| | | sb.append(UUIDUtil.getRandomCode().substring(0, l)); |
| | | str = sb.toString(); |
| | | } else if (num % 32 == 0) { |
| | | Integer s = num / 32; |
| | | StringBuffer sb = new StringBuffer(); |
| | | for (int i = 0; i < s; i++) { |
| | | sb.append(UUIDUtil.getRandomCode()); |
| | | } |
| | | str = sb.toString(); |
| | | } else { |
| | | str = UUIDUtil.getRandomCode().substring(0, num); |
| | | } |
| | | } else { |
| | | throw new Exception("参数只能大于0"); |
| | | } |
| | | return str; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取根据当前时间的字符串数据 |
| | | * |
| | | * @return |
| | | */ |
| | | public synchronized static String getTimeStr() { |
| | | SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddhhmmssS"); |
| | | return simpleDateFormat.format(new Date()); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * @Description: 获取数字随机码 |
| | | * @Author pzb |
| | | * @Date 2021/8/11 16:52 |
| | | * @Param |
| | | * @Return |
| | | * @Exception |
| | | */ |
| | | public static String getNumberRandom(Integer num) { |
| | | if (null == num) { |
| | | num = 32; |
| | | } |
| | | StringBuffer sb = new StringBuffer(); |
| | | for (int i = 0; i < num; i++) { |
| | | sb.append(Double.valueOf(Math.random() * 10).intValue()); |
| | | } |
| | | return sb.toString(); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.util.httpClinet; |
| | | |
| | | import com.alibaba.fastjson.JSON; |
| | | import com.fasterxml.jackson.databind.ObjectMapper; |
| | | import org.apache.http.NameValuePair; |
| | | import org.apache.http.client.config.RequestConfig; |
| | | import org.apache.http.client.entity.UrlEncodedFormEntity; |
| | | import org.apache.http.client.methods.CloseableHttpResponse; |
| | | import org.apache.http.client.methods.HttpGet; |
| | | import org.apache.http.client.methods.HttpPost; |
| | | import org.apache.http.conn.ssl.SSLConnectionSocketFactory; |
| | | import org.apache.http.entity.ContentType; |
| | | import org.apache.http.entity.StringEntity; |
| | | import org.apache.http.impl.client.CloseableHttpClient; |
| | | import org.apache.http.impl.client.HttpClients; |
| | | import org.apache.http.impl.conn.PoolingHttpClientConnectionManager; |
| | | import org.apache.http.message.BasicNameValuePair; |
| | | import org.apache.http.ssl.SSLContexts; |
| | | import org.apache.http.util.EntityUtils; |
| | | import org.slf4j.Logger; |
| | | import org.slf4j.LoggerFactory; |
| | | |
| | | import javax.net.ssl.SSLContext; |
| | | import java.io.File; |
| | | import java.io.FileInputStream; |
| | | import java.io.InputStream; |
| | | import java.nio.charset.Charset; |
| | | import java.security.KeyStore; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | import java.util.concurrent.TimeUnit; |
| | | |
| | | /** |
| | | * http工具类 |
| | | */ |
| | | public class HttpClientUtil { |
| | | |
| | | private static Logger logger = LoggerFactory.getLogger(HttpClientUtil.class); |
| | | |
| | | private static PoolingHttpClientConnectionManager connectionManager; |
| | | |
| | | |
| | | { |
| | | //1.创建连接池管理器 |
| | | connectionManager = new PoolingHttpClientConnectionManager(60000, |
| | | TimeUnit.MILLISECONDS); |
| | | connectionManager.setMaxTotal(1000); |
| | | connectionManager.setDefaultMaxPerRoute(50); |
| | | } |
| | | |
| | | /** |
| | | * 创建一个httpClient对象 |
| | | */ |
| | | private static CloseableHttpClient getHttpCline() { |
| | | return HttpClients.custom() |
| | | .setConnectionManager(connectionManager) |
| | | .disableAutomaticRetries() |
| | | .build(); |
| | | } |
| | | |
| | | private static RequestConfig getRequestConfig() { |
| | | RequestConfig.Builder builder = RequestConfig.custom(); |
| | | builder.setSocketTimeout(60000)//3.1设置客户端等待服务端返回数据的超时时间 |
| | | .setConnectTimeout(30000)//3.2设置客户端发起TCP连接请求的超时时间 |
| | | .setExpectContinueEnabled(true) |
| | | .setConnectionRequestTimeout(30000);//3.3设置客户端从连接池获取链接的超时时间 |
| | | return builder.build(); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 创建一个POST请求实例 |
| | | * |
| | | * @param url 请求地址 |
| | | * @param params 请求参数 |
| | | */ |
| | | public static CloseableHttpResponse setPostHttpRequset(String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception { |
| | | HttpPost httpPost = new HttpPost(url); |
| | | httpPost.setConfig(getRequestConfig()); |
| | | if (null != header) { |
| | | for (String key : header.keySet()) { |
| | | httpPost.setHeader(key, header.get(key)); |
| | | } |
| | | } |
| | | List<NameValuePair> list = new ArrayList<>(); |
| | | if (null != params) { |
| | | Set<String> keys = params.keySet(); |
| | | for (String key : keys) { |
| | | list.add(new BasicNameValuePair(key, null == params.get(key) ? null : params.get(key).toString())); |
| | | } |
| | | } |
| | | switch (contentType) { |
| | | case "form": |
| | | httpPost.setEntity(new UrlEncodedFormEntity(list, "UTF-8")); |
| | | break; |
| | | case "json": |
| | | ObjectMapper objectMapper = new ObjectMapper(); |
| | | String s = objectMapper.writeValueAsString(params); |
| | | httpPost.setEntity(new StringEntity(s, ContentType.create(ContentType.APPLICATION_JSON.getMimeType(), Charset.forName("UTF-8")))); |
| | | break; |
| | | } |
| | | return getHttpCline().execute(httpPost); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 获取get请求实例 |
| | | * |
| | | * @param url 请求地址 |
| | | * @param params 请求参数 |
| | | */ |
| | | private static CloseableHttpResponse setGetHttpRequset(String url, Map<String, Object> params, Map<String, String> header) throws Exception { |
| | | StringBuffer sb = new StringBuffer(); |
| | | String p = ""; |
| | | if (null != params) { |
| | | Set<String> keys = params.keySet(); |
| | | for (String key : keys) { |
| | | sb.append(key + "=" + params.get(key) + "&"); |
| | | } |
| | | p = "?" + sb.substring(0, sb.length() - 1); |
| | | } |
| | | HttpGet httpGet = new HttpGet(url + p); |
| | | httpGet.setConfig(getRequestConfig()); |
| | | if (null != header) { |
| | | for (String key : header.keySet()) { |
| | | httpGet.setHeader(key, header.get(key)); |
| | | } |
| | | } |
| | | return getHttpCline().execute(httpGet); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 发送http请求 |
| | | * |
| | | * @param mothed "GET、POST、PUT、HEAD、DELETE、HEAD、OPTIONS" |
| | | * @param url 请求地址 |
| | | * @param params 请求参数 |
| | | * @param header 请求头 |
| | | * @param contentType 参数请求方式form/json |
| | | * @return |
| | | */ |
| | | public static HttpResult pushHttpRequset(String mothed, String url, Map<String, Object> params, Map<String, String> header, String contentType) throws Exception { |
| | | String randome = UUID.randomUUID().toString(); |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.S"); |
| | | logger.info(sdf.format(new Date()) + "----(" + randome + ")请求参数:" + JSON.toJSONString(params)); |
| | | CloseableHttpResponse httpResponse = null; |
| | | switch (mothed) { |
| | | case "GET": |
| | | httpResponse = setGetHttpRequset(url, params, header); |
| | | break; |
| | | case "POST": |
| | | httpResponse = setPostHttpRequset(url, params, header, contentType); |
| | | break; |
| | | } |
| | | int statusCode = httpResponse.getStatusLine().getStatusCode(); |
| | | String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); |
| | | logger.info(sdf.format(new Date()) + "----(" + randome + ")返回结果:" + content); |
| | | HttpResult httpResult = HttpResult.getHttpResult(statusCode, content); |
| | | close(httpResponse); |
| | | return httpResult; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 发送XML请求 |
| | | * |
| | | * @param url 请求地址 |
| | | * @param xml XML数据 |
| | | * @param header 自定义请求头 |
| | | * @return |
| | | */ |
| | | public static HttpResult pushHttpRequsetXml(String url, String xml, Map<String, String> header) throws Exception { |
| | | HttpPost httpPost = new HttpPost(url); |
| | | httpPost.setConfig(getRequestConfig()); |
| | | for (String key : header.keySet()) { |
| | | httpPost.setHeader(key, header.get(key)); |
| | | } |
| | | httpPost.setHeader("Content-Type", "application/xml"); |
| | | httpPost.setEntity(new StringEntity(xml, "UTF-8")); |
| | | CloseableHttpResponse httpResponse = getHttpCline().execute(httpPost); |
| | | int statusCode = httpResponse.getStatusLine().getStatusCode(); |
| | | String content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); |
| | | HttpResult httpResult = HttpResult.getHttpResult(statusCode, content); |
| | | close(httpResponse); |
| | | return httpResult; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * 请求https发送XML请求 |
| | | * |
| | | * @param url 接口路径 |
| | | * @param xml 内容 |
| | | * @param header 请求头 |
| | | * @param certPassword 证书密码 |
| | | * @param certPath 证书路径 |
| | | * @param certType 证书类型 |
| | | * @return |
| | | * @throws Exception |
| | | */ |
| | | public static String pushHttpsRequsetXml(String url, String xml, Map<String, String> header, String certPassword, String certPath, String certType) throws Exception { |
| | | HttpPost httpPost = new HttpPost(url); |
| | | for (String key : header.keySet()) { |
| | | httpPost.setHeader(key, header.get(key)); |
| | | } |
| | | httpPost.setHeader("Content-Type", "application/xml"); |
| | | httpPost.setEntity(new StringEntity(xml, "UTF-8")); |
| | | CloseableHttpClient httpCline = initCert(certPassword, certPath, certType); |
| | | CloseableHttpResponse httpResponse = httpCline.execute(httpPost); |
| | | String content = null; |
| | | if (httpResponse.getStatusLine().getStatusCode() == 200) { |
| | | content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); |
| | | } else { |
| | | content = "返回状态码:" + httpResponse.getStatusLine() + "。" + EntityUtils.toString(httpResponse.getEntity()); |
| | | } |
| | | close(httpResponse); |
| | | httpCline.close(); |
| | | return content; |
| | | } |
| | | public static String pushHttpsRequsetXml1(String url, String xml, Map<String, String> header, String certPassword, String certPath, String certType) throws Exception { |
| | | HttpPost httpPost = new HttpPost(url); |
| | | for (String key : header.keySet()) { |
| | | httpPost.setHeader(key, header.get(key)); |
| | | } |
| | | httpPost.setHeader("Content-Type", "application/xml"); |
| | | httpPost.setEntity(new StringEntity(xml, "UTF-8")); |
| | | CloseableHttpClient httpCline = initCert1(certPassword, certPath, certType); |
| | | CloseableHttpResponse httpResponse = httpCline.execute(httpPost); |
| | | String content = null; |
| | | if (httpResponse.getStatusLine().getStatusCode() == 200) { |
| | | content = EntityUtils.toString(httpResponse.getEntity(), "UTF-8"); |
| | | } else { |
| | | content = "返回状态码:" + httpResponse.getStatusLine() + "。" + EntityUtils.toString(httpResponse.getEntity()); |
| | | } |
| | | close(httpResponse); |
| | | httpCline.close(); |
| | | return content; |
| | | } |
| | | private static CloseableHttpClient initCert1(String key, String certPath, String certType) throws Exception { |
| | | KeyStore keyStore = KeyStore.getInstance(certType); |
| | | InputStream inputStream = new FileInputStream(new File(certPath)); |
| | | try { |
| | | keyStore.load(inputStream, key.toCharArray()); |
| | | } finally { |
| | | inputStream.close(); |
| | | } |
| | | SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build(); |
| | | SSLConnectionSocketFactory sslsf = |
| | | new SSLConnectionSocketFactory(sslcontext, null, null, |
| | | SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); |
| | | return HttpClients.custom().setSSLSocketFactory(sslsf).build(); |
| | | } |
| | | |
| | | /** |
| | | * 初始化https对象(带证书) |
| | | * |
| | | * @param key 证书密码 |
| | | * @param certPath 证书路径 |
| | | * @param certType 证书类型 |
| | | * @throws Exception |
| | | */ |
| | | private static CloseableHttpClient initCert(String key, String certPath, String certType) throws Exception { |
| | | KeyStore keyStore = KeyStore.getInstance(certType); |
| | | InputStream inputStream = new FileInputStream(new File(certPath)); |
| | | try { |
| | | keyStore.load(inputStream, key.toCharArray()); |
| | | } finally { |
| | | inputStream.close(); |
| | | } |
| | | SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, key.toCharArray()).build(); |
| | | SSLConnectionSocketFactory sslsf = |
| | | new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null, |
| | | SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER); |
| | | return HttpClients.custom().setSSLSocketFactory(sslsf).build(); |
| | | } |
| | | |
| | | |
| | | |
| | | /** |
| | | * 关闭资源 |
| | | */ |
| | | private static void close(CloseableHttpResponse httpResponse) { |
| | | try { |
| | | if (null != httpResponse) { |
| | | EntityUtils.consume(httpResponse.getEntity());//此处高能,通过源码分析,由EntityUtils是否回收HttpEntity |
| | | httpResponse.close(); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } finally { |
| | | try { |
| | | if (null != httpResponse) { |
| | | httpResponse.close(); |
| | | } |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.util.httpClinet; |
| | | |
| | | import lombok.Data; |
| | | |
| | | /** |
| | | * http请求返回封装 |
| | | */ |
| | | @Data |
| | | public class HttpResult { |
| | | /** |
| | | * 返回状态码 |
| | | */ |
| | | private Integer code; |
| | | /** |
| | | * 返回结果 |
| | | */ |
| | | private String data; |
| | | |
| | | /** |
| | | * 返回封装结果 |
| | | * |
| | | * @param code |
| | | * @param data |
| | | * @return |
| | | */ |
| | | public static HttpResult getHttpResult(Integer code, String data) { |
| | | HttpResult httpResult = new HttpResult(); |
| | | httpResult.setCode(code); |
| | | httpResult.setData(data); |
| | | return httpResult; |
| | | } |
| | | } |
| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ruoyi.common.core.utils.StringUtils; |
| | | import com.ruoyi.other.util.UUIDUtil; |
| | | import com.ruoyi.other.util.payment.model.*; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.net.InetAddress; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.*; |
| | | |
| | | /** |
| | |
| | | */ |
| | | @Slf4j |
| | | public class PaymentUtil { |
| | | |
| | | |
| | | //微信公众号、微信小程序、微信 APP+/H5、云微小程序支付 |
| | | private static final String appId = "wxdeed472c98e42a54"; |
| | | private static final String appId = "wx049faf9c5234f31c"; |
| | | /** |
| | | * 商户密钥 |
| | | */ |
| | | private static final String key = "925899fcc374430f9e4b4ba3db05b448"; |
| | | private static final String key = "ss369875124965782f148539657826321"; |
| | | /** |
| | | * 商户号 |
| | | */ |
| | | private static final String merchantNo = "888122600004175"; |
| | | private static final String merchantNo = "1717539630"; |
| | | /** |
| | | * 平台-报备商户号 |
| | | */ |
| | | private static final String sysTradeMerchantNo = "777168500885852"; |
| | | private static final String sysTradeMerchantNo = ""; |
| | | /** |
| | | * 支付回调地址 |
| | | */ |
| | | private static final String callbackUrl = "https://www.qijisheng.top"; |
| | | private static final String callbackUrl = "https://221.182.45.100:8084"; |
| | | |
| | | |
| | | /** |
| | |
| | | UniPayResult uniPayResult = JSON.parseObject(execute.body(), UniPayResult.class); |
| | | return uniPayResult; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * native支付 |
| | | * @param orderNo 商户订单号 |
| | | * @param amount 订单金额 |
| | | * @param notifyUrl 服务器异步通知地址 |
| | | * @return |
| | | */ |
| | | public static String nativePay(String orderNo, BigDecimal amount, String notifyUrl) throws Exception { |
| | | int totalFee = amount.multiply(new BigDecimal("100")).intValue(); |
| | | |
| | | String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; |
| | | |
| | | // 构建 XML 请求体 |
| | | Map<String, Object> params = new HashMap<>(); |
| | | params.put("appid", appId); |
| | | params.put("mch_id", merchantNo); |
| | | params.put("nonce_str", UUIDUtil.getRandomCode(16)); |
| | | params.put("body", "积分充值"); |
| | | params.put("out_trade_no", orderNo); |
| | | params.put("total_fee", totalFee); |
| | | // params.put("spbill_create_ip", InetAddress.getLocalHost().getHostAddress()); |
| | | params.put("spbill_create_ip", "221.182.45.100"); |
| | | params.put("notify_url", "https://221.182.45.100:8084/undif"); |
| | | params.put("trade_type", "NATIVE"); |
| | | params.put("product_id", "1"); |
| | | |
| | | String sign = sign1(JSONObject.from(params)); // 使用原来的 sign 方法 |
| | | params.put("sign", sign); |
| | | |
| | | String xmlBody = mapToXml(params); // 转换为 XML 字符串 |
| | | |
| | | // 发送请求 |
| | | HttpRequest post = HttpUtil.createPost(url); |
| | | post.header(Header.CONTENT_TYPE, "application/xml"); |
| | | post.body(xmlBody); // 发送原始 XML 字符串 |
| | | |
| | | log.info("Native支付接口请求参数:" + xmlBody); |
| | | HttpResponse execute = post.execute(); |
| | | log.info("Native支付接口请求响应:" + execute.body()); |
| | | |
| | | if (execute.getStatus() != 200) { |
| | | log.error("Native支付接口异常:" + execute.body()); |
| | | return null; |
| | | } |
| | | return execute.body(); |
| | | } |
| | | private static String mapToXml(Map<String, Object> map) { |
| | | StringBuilder sb = new StringBuilder(); |
| | | sb.append("<xml>"); |
| | | for (Map.Entry<String, Object> entry : map.entrySet()) { |
| | | String key = entry.getKey(); |
| | | Object value = entry.getValue(); |
| | | if (value != null && !value.toString().isEmpty()) { |
| | | sb.append("<").append(key).append(">"); |
| | | sb.append(value); |
| | | sb.append("</").append(key).append(">"); |
| | | } |
| | | } |
| | | sb.append("</xml>"); |
| | | return sb.toString(); |
| | | } |
| | | public static String sign1(JSONObject body) { |
| | | Set<Map.Entry<String, Object>> entries = body.entrySet(); |
| | | List<Map.Entry<String, Object>> infoIds = new ArrayList<>(entries); |
| | | |
| | | // 排除 sign 字段本身 |
| | | infoIds.removeIf(entry -> "sign".equals(entry.getKey())); |
| | | |
| | | // 按 ASCII 顺序排序 |
| | | infoIds.sort(Map.Entry.comparingByKey()); |
| | | |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (Map.Entry<String, Object> entry : infoIds) { |
| | | Object val = entry.getValue(); |
| | | if (val != null && !val.toString().trim().isEmpty()) { |
| | | sb.append(entry.getKey()).append("=").append(val).append("&"); |
| | | } |
| | | } |
| | | |
| | | // 最后拼接 &key=商户密钥 |
| | | sb.append("key=").append(key); |
| | | |
| | | String stringSignTemp = sb.toString(); |
| | | log.info("待签名串:{}", stringSignTemp); |
| | | |
| | | // 使用 MD5 加密 |
| | | return MD5AndKL.MD5(stringSignTemp); |
| | | } |
| | | |
| | | /** |
| | | * 微信下单的签名算法 |
| | | * |
| | | * @param map |
| | | * @return |
| | | */ |
| | | private String weixinSignature(Map<String, Object> map) { |
| | | try { |
| | | Set<Map.Entry<String, Object>> entries = map.entrySet(); |
| | | List<Map.Entry<String, Object>> infoIds = new ArrayList<Map.Entry<String, Object>>(entries); |
| | | // 对所有传入参数按照字段名的 ASCII 码从小到大排序(字典序) |
| | | Collections.sort(infoIds, new Comparator<Map.Entry<String, Object>>() { |
| | | public int compare(Map.Entry<String, Object> o1, Map.Entry<String, Object> o2) { |
| | | return (o1.getKey()).toString().compareTo(o2.getKey()); |
| | | } |
| | | }); |
| | | // 构造签名键值对的格式 |
| | | StringBuilder sb = new StringBuilder(); |
| | | for (Map.Entry<String, Object> item : infoIds) { |
| | | if (item.getKey() != null || item.getKey() != "") { |
| | | String key = item.getKey(); |
| | | Object val = item.getValue(); |
| | | if (!(val == "" || val == null)) { |
| | | sb.append(key + "=" + val + "&"); |
| | | } |
| | | } |
| | | } |
| | | sb.append("key=" + key); |
| | | String sign = MD5AndKL.MD5Encode(sb.toString(), "UTF-8").toUpperCase(); //注:MD5签名方式 |
| | | return sign; |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | } |
| | | return null; |
| | | } |
| | | public static void main(String[] args) throws Exception { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
| | | String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); |
| | | String string = PaymentUtil.nativePay(code,new BigDecimal("0.1"), |
| | | "/test" |
| | | ); |
| | | System.err.println(string); |
| | | } |
| | | /** |
| | | * 查询支付订单 |
| | | * @param orderNo 订单号 |
| | |
| | | } |
| | | |
| | | |
| | | public static void main(String[] args) { |
| | | // UniPayResult uniPayResult = PaymentUtil.uniPay("852963742", 0.01D, "测试商品", "这是用于对接支付测试的商品描述", |
| | | // "", "/order/shopping-cart/shoppingCartPaymentCallback", "ooOrs64zHLuInkZ_GF0LpIN9_Rxc", "777168500885852"); |
| | | // PaymentUtil.queryOrder("852963742"); |
| | | // PaymentUtil.closeOrder("852963742"); |
| | | |
| | | } |
| | | |
| | | } |
| | |
| | | import com.alibaba.fastjson2.JSON; |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.other.util.payment.MD5AndKL; |
| | | import com.ruoyi.other.util.payment.wx.WechatPayConfig; |
| | | import com.ruoyi.other.util.payment.wx.XMLUtil; |
| | | import org.apache.commons.codec.digest.DigestUtils; |
| | | import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; |
| | | import org.bouncycastle.crypto.engines.AESEngine; |
| | | import org.bouncycastle.crypto.paddings.PKCS7Padding; |
| | | import org.bouncycastle.crypto.paddings.PaddedBufferedBlockCipher; |
| | | import org.bouncycastle.crypto.params.KeyParameter; |
| | | import org.bouncycastle.jce.provider.BouncyCastleProvider; |
| | | import org.bouncycastle.openssl.PEMParser; |
| | | import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter; |
| | |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.util.StringUtils; |
| | | import sun.misc.BASE64Decoder; |
| | | import sun.security.util.DerInputStream; |
| | | import sun.security.util.DerValue; |
| | | |
| | |
| | | import javax.crypto.Cipher; |
| | | import javax.crypto.IllegalBlockSizeException; |
| | | import javax.crypto.NoSuchPaddingException; |
| | | import javax.crypto.spec.IvParameterSpec; |
| | | import javax.crypto.spec.SecretKeySpec; |
| | | import javax.net.ssl.HttpsURLConnection; |
| | | import javax.net.ssl.KeyManagerFactory; |
| | | import javax.net.ssl.SSLContext; |
| | | import javax.servlet.http.HttpServletRequest; |
| | | import javax.servlet.http.HttpServletResponse; |
| | | import java.io.*; |
| | | import java.math.BigDecimal; |
| | | import java.math.BigInteger; |
| | | import java.net.InetAddress; |
| | | import java.net.URL; |
| | | import java.net.URLEncoder; |
| | | import java.net.UnknownHostException; |
| | | import java.nio.charset.StandardCharsets; |
| | | import java.nio.file.Files; |
| | |
| | | import java.security.spec.RSAPublicKeySpec; |
| | | import java.security.spec.X509EncodedKeySpec; |
| | | import java.util.*; |
| | | import java.util.stream.Collectors; |
| | | |
| | | /** |
| | | * 微信支付服务类 |
| | |
| | | @Autowired |
| | | private WechatPayConfig wechatPayConfig; |
| | | private static final String RSA_PUBLIC_KEY_FILENAME = "wechat_rsa_public_key.pem"; |
| | | private static final String CERT_FOLDER = "C:\\cert\\"; |
| | | private static final String CERT_FOLDER = "cert/"; |
| | | /** |
| | | * 统一下单 |
| | | * native统一下单 |
| | | * @param orderNumber 订单号 |
| | | * @param totalFee 总金额(分) |
| | | * @param body 商品描述 |
| | | * @param openid 用户openid |
| | | * @return 预支付订单信息 |
| | | */ |
| | | public R unifiedOrder(String orderNumber, String totalFee, String body, String openid, String callbackPath) throws Exception { |
| | | public Map<String, String> unifiedOrder(String orderNumber, String totalFee, |
| | | String body, |
| | | String callbackPath) throws Exception { |
| | | int i = new BigDecimal(totalFee).multiply(new BigDecimal("100")).intValue(); |
| | | String hostAddress = null; |
| | | try { |
| | |
| | | params.put("out_trade_no", orderNumber); |
| | | params.put("total_fee", String.valueOf(i) ); |
| | | params.put("spbill_create_ip", "221.182.45.100"); // 实际应用中应获取客户端IP |
| | | params.put("notify_url", wechatPayConfig.getCallbackPath()+callbackPath); |
| | | params.put("trade_type", "JSAPI"); |
| | | params.put("openid", openid); |
| | | |
| | | params.put("notify_url", "http://221.182.45.100:8084"+callbackPath); |
| | | params.put("trade_type", "NATIVE"); |
| | | // 生成签名 |
| | | String sign = weixinSignature(params); |
| | | params.put("sign", sign); |
| | | |
| | | // 将参数转换为XML |
| | | String xmlParams = XMLUtil.mapToXml(params).replaceFirst("^<\\?xml.+?\\?>\\s*", ""); |
| | | |
| | | // 发送请求到微信支付统一下单接口 |
| | | String url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; |
| | | String result = HttpUtil.post(url, xmlParams); |
| | | |
| | | // 解析返回结果 |
| | | Map<String, String> resultMap = XMLUtil.xmlToMap(result); |
| | | |
| | | // 验证签名 |
| | | if (!verifySign(resultMap, wechatPayConfig.getKey())) { |
| | | return R.fail("微信支付签名验证失败"); |
| | | // throw new Exception("微信支付签名验证失败"); |
| | | throw new Exception("微信支付签名验证失败"); |
| | | } |
| | | if (!resultMap.get("return_code").equals("SUCCESS")) { |
| | | throw new Exception("拉取支付失败"); |
| | | |
| | | // 构建小程序支付所需参数 |
| | | Map<String, String> payParams = new HashMap<>(); |
| | | payParams.put("appId", wechatPayConfig.getAppId()); |
| | | payParams.put("timeStamp", String.valueOf(System.currentTimeMillis() / 1000)); |
| | | payParams.put("nonceStr", generateNonceStr()); |
| | | payParams.put("package", "prepay_id=" + resultMap.get("prepay_id")); |
| | | payParams.put("signType", "MD5"); |
| | | |
| | | // 生成支付签名 |
| | | String paySign = weixinSignature(payParams); |
| | | payParams.put("paySign", paySign); |
| | | |
| | | //给前端标识 |
| | | payParams.put("payMethod","1"); |
| | | return R.ok(JSON.toJSONString(payParams)); |
| | | } |
| | | resultMap.put("code",orderNumber); |
| | | return resultMap; |
| | | } |
| | | /** |
| | | * 微信下单的签名算法 |
| | |
| | | try { |
| | | // 1. 解析回调XML数据 |
| | | if (StringUtils.isEmpty(xmlData)) { |
| | | // logger.error("退款回调数据为空"); |
| | | return RefundCallbackResult.fail("回调数据为空"); |
| | | } |
| | | |
| | | //2.解析参数 |
| | | System.err.println(xmlData); |
| | | System.out.println(xmlData); |
| | | System.out.println("----------------------------------------"); |
| | | Map<String, String> resultMap = XMLUtil.xmlToMap(xmlData); |
| | | System.out.println(resultMap.get("req_info")); |
| | |
| | | } |
| | | |
| | | //4 使用商户API密钥解密req_info(AES-256-CBC算法) |
| | | String decryptData = wxDecrypt(resultMap.get("req_info"), wechatPayConfig.getKey()); |
| | | String decryptData = decrypt(resultMap.get("req_info"), wechatPayConfig.getKey()); |
| | | Map<String, String> refundDetail = XMLUtil.xmlToMap(decryptData); |
| | | |
| | | |
| | |
| | | } |
| | | |
| | | /** |
| | | * 加载公钥 返回PublicKey |
| | | * 加载公钥 返回PublicKey对象 |
| | | */ |
| | | public static PublicKey loadPublicKey(String pemContent) throws Exception { |
| | | // 读取PEM文件内容 |
| | |
| | | } |
| | | |
| | | public static void main(String[] args) throws IOException { |
| | | /* |
| | | try { |
| | | // 1. 加载公钥 |
| | | PublicKey publicKey = loadPublicKey(); |
| | | |
| | | // 2. 加密数据 |
| | | String sensitiveData = "用户名"; |
| | | String encryptedData = encrypt(sensitiveData, publicKey); |
| | | String info="CjlaS7RVnPn7zzP5ByZDxUN7OrXGp1/DEdO0qahpIqDH/gTNHb/U7VmrVV0S4lXrIa0N8FEREC3CdIeT4XB5P4D0E8TSURu6J/cD01hFu28f0JDRfeips3vSpTgznRGyCfnUBDPYwyrVeP29Wac7WAb3CCcJf7OZWaweOUkaKjaBRa1GzMZcguSZnQJz0cD5Jb4HbTMvM0VAebfCY9aXdfFBIbm+cPYESo3awqwkNTQeT4V+FViw8f8sjkH0TScMgWBiSKmQC837BLD27yIGklqlYkDP2IMeiNw+b12qCAGszfp2vYd3X+HpViXkQQet3PJWYlAm55R+IgvschP7Ub65XzLINfQrJKrQUXiKKO2LwoSRSwZvfDkR8G8E8X59CnU2XvWKeos5Y0q8ckbJb97yI+09nNgMjYyJoVCVjTFgFMDEQ4+e3CpYRhD6V/3RBp+TvBwszldbRav2XEuCXL2kCJyJEAqLPMNyfYBSNF8z1btjyz0+y/xQQcySKlQInZ710FxSE7KwRSBQ92j9nDdlR7UxCrPVCkEd+GrVNSqqnyjNh1J/rPJPHvvGwkPPq72TKiw6ZgaIgIDhy0/lWHTclo4sjYAWuUVfg3CJ8dqkuQwVZ7i0+NiahIl78RtcUph8NR48yUgBkN7WhCcu5wLbg2tu8Qe0SIwHF+RW1x9Yc8akEkNbMd4xzs8lY5MYEU9V16U8RyWJuwPDph3RnmV8HQ+2hfzmjCvPkBwtfR8P5VdK86OIsHfnfQxAcPM2a86tOBBzFXPrLHgd2CRcDKH+MXTw7RSH/bk1PiMUAWF8TQsNDzgUlznJnkjiQxoym/4ZUf4C6072KKQHbp6bgBYkBhJLT2lmjVMNSX5b1SXM9eTQixRfq6MKGw3P8XJnKdofktVv+KtSzWQlW0C8p504NWACiExupF5EII7FG+xCWt7urWUbc4NRI36UFrKToQCLVv6UBCXt/t9iWlvs6SfuZhpCexeMmZWeiIldzRu87U9rXR46Hu7DAL8dZ+0ItsIZYThSIABzZgaLKggXlkjyAcbcPYKO7egrCmDtFhzHuh4uA3VeBylL3/ZLZ4FUedn/8L4e2iAu22Qj46ORlu17W5R8Ez9kubydeAgC9PkWnjptaubPxE0bjPN69tec"; |
| | | |
| | | System.out.println("加密结果(Base64):\n" + encryptedData); |
| | | } catch (Exception e) { |
| | | e.printStackTrace(); |
| | | }*/ |
| | | |
| | | String info="CjlaS7RVnPn7zzP5ByZDxUN7OrXGp1/DEdO0qahpIqDH/gTNHb/U7VmrVV0S4lXrIa0N8FEREC3CdIeT4XB5P4D0E8TSURu6J/cD01hFu2/uJOvcE6EeQH2xiRg/Wir4qcW7c6uTiLoqyirCQXcGzQb3CCcJf7OZWaweOUkaKjaBRa1GzMZcguSZnQJz0cD5jTMx+Tch5+b7jBq5PrTFxtMSH/DAG+kgkRazDFnEzkMeT4V+FViw8f8sjkH0TScMgWBiSKmQC837BLD27yIGklqlYkDP2IMeiNw+b12qCAGszfp2vYd3X+HpViXkQQet3PJWYlAm55R+IgvschP7Ub65XzLINfQrJKrQUXiKKO2LwoSRSwZvfDkR8G8E8X59CnU2XvWKeos5Y0q8ckbJb97yI+09nNgMjYyJoVCVjTGc7ghcYvWKbqanJ8bSFqiBCIqLSXsRR2DmJIxHq9fGE72kCJyJEAqLPMNyfYBSNF8z1btjyz0+y/xQQcySKlQInZ710FxSE7KwRSBQ92j9nDdlR7UxCrPVCkEd+GrVNSqqnyjNh1J/rPJPHvvGwkPPq72TKiw6ZgaIgIDhy0/lWHTclo4sjYAWuUVfg3CJ8dqkuQwVZ7i0+NiahIl78RtcUph8NR48yUgBkN7WhCcu5wLbg2tu8Qe0SIwHF+RW1x9Yc8akEkNbMd4xzs8lY5MYEU9V16U8RyWJuwPDph3RnmV8HQ+2hfzmjCvPkBwtfR8P5VdK86OIsHfnfQxAcPM2a86tOBBzFXPrLHgd2CRcDKH+MXTw7RSH/bk1PiMUAWF8TQsNDzgUlznJnkjiQxoym/4ZUf4C6072KKQHbp6bgBYkBhJLT2lmjVMNSX5b1SXM9eTQixRfq6MKGw3P8XJnKdofktVv+KtSzWQlW0C8p504NWACiExupF5EII7FG+xbTa/s7vxXCP7R98tpcQTGoQCLVv6UBCXt/t9iWlvs6SfuZhpCexeMmZWeiIldzRu87U9rXR46Hu7DAL8dZ+0ItsIZYThSIABzZgaLKggXlkjyAcbcPYKO7egrCmDtFhwN50V7hoXEQB8G5kf/lMuT5+xNE2FRmv7H2a0ttZiv4u17W5R8Ez9kubydeAgC9PkWnjptaubPxE0bjPN69tec"; |
| | | String key="fD0JzscfMf295SYtRK3MnPRjSCA4Gahr"; |
| | | try { |
| | | String decrypted = decrypt(info, key); |
| | |
| | | |
| | | |
| | | public static String decrypt(String encryptedStringA, String merchantKey) throws Exception { |
| | | try { |
| | | byte[] decode = Base64.getDecoder().decode(encryptedStringA); |
| | | String sign = MD5AndKL.MD5Encode(merchantKey, "UTF-8").toLowerCase(); |
| | | System.out.println("MD5 Key: " + sign); // 调试输出 |
| | | // 1. 对加密串A做base64解码,得到加密串B |
| | | byte[] decode = Base64.getDecoder().decode(encryptedStringA); |
| | | |
| | | if (Security.getProvider("BC") == null) { |
| | | Security.addProvider(new BouncyCastleProvider()); |
| | | } |
| | | // 2. 对商户key做md5,得到32位小写key* |
| | | String sign = MD5AndKL.MD5Encode(merchantKey, "UTF-8").toLowerCase(); |
| | | |
| | | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); |
| | | byte[] aesKey = Arrays.copyOf(sign.getBytes("UTF-8"), 16); // 明确指定 UTF-8 |
| | | SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, "AES"); |
| | | cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); |
| | | |
| | | byte[] decryptedBytes = cipher.doFinal(decode); |
| | | return new String(decryptedBytes, "UTF-8"); // 明确指定 UTF-8 |
| | | } catch (Exception e) { |
| | | System.err.println("解密失败: " + e.getMessage()); |
| | | throw e; |
| | | // 3. 确保BouncyCastle提供者已添加 |
| | | if (Security.getProvider("BC") == null) { |
| | | Security.addProvider(new BouncyCastleProvider()); |
| | | } |
| | | |
| | | // 4. 使用AES-256-ECB解密(PKCS7Padding) |
| | | Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding", "BC"); |
| | | |
| | | // 注意:微信要求使用AES-256,所以密钥应为32字节(256位) |
| | | // 如果MD5结果是32字节(256位),直接使用 |
| | | byte[] aesKey = sign.getBytes(StandardCharsets.UTF_8); |
| | | |
| | | SecretKeySpec secretKeySpec = new SecretKeySpec(aesKey, "AES"); |
| | | cipher.init(Cipher.DECRYPT_MODE, secretKeySpec); |
| | | |
| | | // 执行解密并指定UTF-8编码 |
| | | byte[] decryptedBytes = cipher.doFinal(decode); |
| | | return new String(decryptedBytes, StandardCharsets.UTF_8); |
| | | } |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.vo; |
| | | |
| | | import com.ruoyi.common.core.web.page.BasePage; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "积分明细列表返回VO") |
| | | public class IntegralListVO extends IntegralRecord { |
| | | |
| | | @ApiModelProperty("用户名") |
| | | private String appUserName; |
| | | @ApiModelProperty("手机号") |
| | | private String phone; |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.vo; |
| | | |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "积分钱包VO") |
| | | public class IntegralVO { |
| | | |
| | | @ApiModelProperty("积分数") |
| | | private Integer integral; |
| | | @ApiModelProperty("积分明细") |
| | | private PageInfo<IntegralListVO> integralList; |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.vo; |
| | | |
| | | import com.ruoyi.other.api.domain.IntegralRecord; |
| | | import com.ruoyi.other.api.domain.ServicePay; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | @Data |
| | | @ApiModel(value = "积分明细列表返回VO") |
| | | public class ServiceListVO extends ServicePay { |
| | | |
| | | |
| | | } |
New file |
| | |
| | | package com.ruoyi.other.vo; |
| | | |
| | | import com.fasterxml.jackson.annotation.JsonFormat; |
| | | import com.ruoyi.common.core.web.page.PageInfo; |
| | | import io.swagger.annotations.ApiModel; |
| | | import io.swagger.annotations.ApiModelProperty; |
| | | import lombok.Data; |
| | | |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Data |
| | | @ApiModel(value = "服务费VO") |
| | | public class ServiceVO { |
| | | |
| | | @ApiModelProperty("到期时间") |
| | | @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") |
| | | private LocalDateTime endTime; |
| | | @ApiModelProperty("状态 1未缴纳 2已过期 3已缴纳") |
| | | private Integer status; |
| | | @ApiModelProperty("缴纳明细") |
| | | private PageInfo<ServiceListVO> serviceList; |
| | | } |
| | |
| | | allow-circular-references: true |
| | | profiles: |
| | | # 环境配置 |
| | | # active: dev |
| | | active: prod |
| | | active: dev |
| | | # active: prod |
| | | --- |
| | | spring: |
| | | config: |
New file |
| | |
| | | <?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.ruoyi.other.mapper.IntegralRecordMapper"> |
| | | |
| | | |
| | | <select id="integralPageList" resultType="com.ruoyi.other.vo.IntegralListVO"> |
| | | select * from t_integral_record |
| | | where 1=1 |
| | | <if test="query.integralType != null "> |
| | | and integral_type = 1 |
| | | </if> |
| | | and site_id = #{query.siteId} |
| | | and delFlag = 0 |
| | | order by create_time desc |
| | | </select> |
| | | </mapper> |
New file |
| | |
| | | <?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.ruoyi.other.mapper.ServicePayMapper"> |
| | | |
| | | |
| | | <select id="servicePageList" resultType="com.ruoyi.other.vo.ServiceListVO"> |
| | | select * from |
| | | t_service_pay |
| | | where 1= 1 |
| | | <if test="query.userId != null"> |
| | | and user_id = #{query.userId} |
| | | </if> |
| | | and payStatus =1 |
| | | order by pay_time desc |
| | | </select> |
| | | </mapper> |
New file |
| | |
| | | package com.ruoyi.other; |
| | | |
| | | import com.ruoyi.common.core.domain.R; |
| | | import com.ruoyi.other.RuoYiOtherApplication; |
| | | import com.ruoyi.other.util.MyQrCodeUtil; |
| | | import com.ruoyi.other.util.ObsUploadUtil; |
| | | import com.ruoyi.other.util.QRCodeUtil; |
| | | import com.ruoyi.other.util.UUIDUtil; |
| | | import com.ruoyi.other.util.payment.wx.WechatPayService; |
| | | import org.apache.tomcat.util.http.fileupload.ByteArrayOutputStream; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | import org.springframework.core.io.ByteArrayResource; |
| | | import org.springframework.mock.web.MockMultipartFile; |
| | | import org.springframework.web.multipart.MultipartFile; |
| | | |
| | | import javax.annotation.Resource; |
| | | import javax.imageio.ImageIO; |
| | | import java.awt.image.BufferedImage; |
| | | import java.io.IOException; |
| | | import java.text.SimpleDateFormat; |
| | | import java.util.Date; |
| | | import java.util.Map; |
| | | |
| | | @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = RuoYiOtherApplication.class) |
| | | public class RuoYiOtherApplicationTests { |
| | | @Resource |
| | | private WechatPayService wechatPayService; |
| | | @Test |
| | | public void contextLoads() throws Exception { |
| | | SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssSSS"); |
| | | String code = sdf.format(new Date()) + UUIDUtil.getNumberRandom(5); |
| | | Map<String,String> r = wechatPayService.unifiedOrder(code, "0.01", "积分充值", "/other/wx/integralCallback"); |
| | | System.err.println(r); |
| | | String codeUrl = r.get("code_url"); |
| | | MyQrCodeUtil.createCodeToFile(codeUrl); |
| | | BufferedImage blueImage = QRCodeUtil.createImage(codeUrl); |
| | | MultipartFile blueFile = convert(blueImage, new Date().getTime() + UUIDUtil.getRandomCode(3) + ".PNG"); |
| | | String s = ObsUploadUtil.obsUpload(blueFile); |
| | | System.err.println(s); |
| | | |
| | | } |
| | | public static MultipartFile convert(BufferedImage bufferedImage, String fileName) throws IOException { |
| | | // 将 BufferedImage 转换为字节数组 |
| | | ByteArrayOutputStream baos = new ByteArrayOutputStream(); |
| | | ImageIO.write(bufferedImage, "png", baos); |
| | | byte[] bytes = baos.toByteArray(); |
| | | |
| | | // 创建 ByteArrayResource |
| | | ByteArrayResource resource = new ByteArrayResource(bytes); |
| | | |
| | | // 创建 MockMultipartFile |
| | | MockMultipartFile multipartFile = new MockMultipartFile( |
| | | "file", |
| | | fileName, |
| | | "image/png", |
| | | resource.getInputStream() |
| | | ); |
| | | |
| | | return multipartFile; |
| | | } |
| | | } |