旗开得胜
This commit is contained in:
parent
ea6050ae6f
commit
1ece8e03a2
43
pom.xml
43
pom.xml
|
@ -103,6 +103,49 @@
|
||||||
<version>2.2</version>
|
<version>2.2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<!-- 工具类-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>cn.hutool</groupId>
|
||||||
|
<artifactId>hutool-all</artifactId>
|
||||||
|
<version>5.8.26</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- redis -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- Gson-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
<version>2.8.8</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- 微信支付 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||||
|
<artifactId>wechatpay-java</artifactId>
|
||||||
|
<version>0.2.12</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.wechatpay-apiv3</groupId>
|
||||||
|
<artifactId>wechatpay-apache-httpclient</artifactId>
|
||||||
|
<version>0.4.9</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 微信小程序 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.binarywang</groupId>
|
||||||
|
<artifactId>wx-java-miniapp-spring-boot-starter</artifactId>
|
||||||
|
<version>4.4.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.greenorange.promotion.config;
|
||||||
|
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
|
||||||
|
import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
public class RedisConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
|
||||||
|
RedisTemplate<String, Object> redisTemplate = new RedisTemplate<>();
|
||||||
|
redisTemplate.setConnectionFactory(factory);
|
||||||
|
|
||||||
|
// 指定kv的序列化方式
|
||||||
|
Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
|
||||||
|
redisTemplate.setValueSerializer(jackson2JsonRedisSerializer);
|
||||||
|
redisTemplate.setKeySerializer(new StringRedisSerializer());
|
||||||
|
|
||||||
|
return redisTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.greenorange.promotion.config;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序获取token响应体
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class WxAccessToken implements Serializable {
|
||||||
|
|
||||||
|
@Schema(description = "获取到的凭证")
|
||||||
|
private String access_token;
|
||||||
|
|
||||||
|
@Schema(description = "凭证有效时间,单位:秒。目前是7200秒之内的值。")
|
||||||
|
private String expires_in;
|
||||||
|
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
}
|
|
@ -0,0 +1,137 @@
|
||||||
|
package com.greenorange.promotion.controller.wechat;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.greenorange.promotion.common.BaseResponse;
|
||||||
|
import com.greenorange.promotion.common.ErrorCode;
|
||||||
|
import com.greenorange.promotion.common.ResultUtils;
|
||||||
|
import com.greenorange.promotion.config.WxAccessToken;
|
||||||
|
import com.greenorange.promotion.service.wechat.WechatGetQrcodeService;
|
||||||
|
import com.greenorange.promotion.utils.QRCodeUtil;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@Tag(name = "获取二维码模块")
|
||||||
|
@RequestMapping("/qrcode")
|
||||||
|
public class WechatGetQrcodeController {
|
||||||
|
|
||||||
|
|
||||||
|
private final static String ACCESS_TOKEN_KEY = "accessToken";
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WechatGetQrcodeService wechatGetQrcodeService;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (小程序端)获取接口调用凭据
|
||||||
|
*/
|
||||||
|
@GetMapping("/get/token")
|
||||||
|
@Operation(summary = "(小程序端)获取接口调用凭据", description = "参数:无, 权限:所有人, 方法名:getAccessToken")
|
||||||
|
public BaseResponse<WxAccessToken> getAccessToken() {
|
||||||
|
String accessToken = (String) redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
|
||||||
|
if (accessToken == null) {
|
||||||
|
accessToken = wechatGetQrcodeService.getAccessToken().getAccess_token();
|
||||||
|
}
|
||||||
|
WxAccessToken wxAccessToken = WxAccessToken.builder()
|
||||||
|
.access_token(accessToken)
|
||||||
|
.expires_in("7200").build();
|
||||||
|
return ResultUtils.success(wxAccessToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序获取二维码
|
||||||
|
*/
|
||||||
|
@PostMapping("/get/qrcode")
|
||||||
|
@Operation(summary = "微信小程序获取二维码", description = "参数:无, 权限:所有人, 方法名:getQrcode")
|
||||||
|
public BaseResponse<String> getQrcode(HttpServletRequest request) throws IOException {
|
||||||
|
String accessToken = (String) redisTemplate.opsForValue().get(ACCESS_TOKEN_KEY);
|
||||||
|
if (accessToken == null) {
|
||||||
|
accessToken = wechatGetQrcodeService.getAccessToken().getAccess_token();
|
||||||
|
}
|
||||||
|
Map<String, Object> param = new HashMap<>();
|
||||||
|
param.put("page", "pages/test/test");
|
||||||
|
param.put("scene", "a=1");
|
||||||
|
param.put("width", 430); // 宽度
|
||||||
|
param.put("check_path", false);
|
||||||
|
param.put("env_version", "develop");
|
||||||
|
String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;
|
||||||
|
String jsonParams = JSONUtil.toJsonStr(param);
|
||||||
|
byte[] responseBytes = HttpUtil.createPost(url)
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.body(jsonParams)
|
||||||
|
.execute()
|
||||||
|
.bodyBytes();
|
||||||
|
|
||||||
|
|
||||||
|
// 将二维码数据转换为 BufferedImage
|
||||||
|
BufferedImage qrImage = ImageIO.read(new ByteArrayInputStream(responseBytes));
|
||||||
|
// 获取用户头像
|
||||||
|
String avatarUrl = "https://img.picui.cn/free/2025/04/09/67f5d7bd6b368.jpg"; // 假设这是用户头像的URL
|
||||||
|
BufferedImage avatarImage = QRCodeUtil.getScaledAvatar(avatarUrl, 188, 188);
|
||||||
|
// 获取空白图像
|
||||||
|
String blankUrl = "https://www.helloimg.com/i/2025/04/07/67f34b0490d07.png";
|
||||||
|
// 加载一张空白图片来覆盖logo(假设是透明背景的图片)
|
||||||
|
BufferedImage blankImage = QRCodeUtil.getScaledAvatar(blankUrl, 196, 196); // 空白图片路径
|
||||||
|
// 将头像转换为圆形
|
||||||
|
BufferedImage circularAvatar = QRCodeUtil.getCircularImage(avatarImage);
|
||||||
|
// 将空白头像转换为圆形
|
||||||
|
BufferedImage circularBlank = QRCodeUtil.getCircularImage(blankImage);
|
||||||
|
// 合并二维码和空白图片
|
||||||
|
BufferedImage mergedWithBlank = QRCodeUtil.addImages(qrImage, circularBlank, 116, 116); // 偏移量根据需要调整
|
||||||
|
// 合并二维码和头像
|
||||||
|
BufferedImage resultImage = QRCodeUtil.addImages(mergedWithBlank, circularAvatar, 120, 120);
|
||||||
|
// 将合成后的图片转换为 Base64 编码
|
||||||
|
InputStream resultStream = QRCodeUtil.bufferedImageToInputStream(resultImage);
|
||||||
|
byte[] resultBytes = resultStream.readAllBytes();
|
||||||
|
|
||||||
|
|
||||||
|
// 生成图片并保存
|
||||||
|
try (FileOutputStream fos = new FileOutputStream("qrcode.png")) {
|
||||||
|
fos.write(resultBytes); // 将二进制数据写入文件
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return ResultUtils.error(ErrorCode.OPERATION_ERROR, "保存二维码图片失败");
|
||||||
|
}
|
||||||
|
// 将二维码转换为Base64编码
|
||||||
|
String base64Image = "data:image/jpeg;base64," + Base64.getEncoder().encodeToString(responseBytes);
|
||||||
|
return ResultUtils.success(base64Image);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.greenorange.promotion.controller.wechat;
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.core.util.RandomUtil;
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.greenorange.promotion.common.BaseResponse;
|
||||||
|
import com.greenorange.promotion.common.ErrorCode;
|
||||||
|
import com.greenorange.promotion.common.ResultUtils;
|
||||||
|
import com.greenorange.promotion.utils.OrderNumberUtils;
|
||||||
|
import com.greenorange.promotion.utils.QRCodeUtil;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Slf4j
|
||||||
|
@RestController
|
||||||
|
@Tag(name = "微信提现模块")
|
||||||
|
@RequestMapping("/payouts")
|
||||||
|
public class WechatPayoutsController {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信小程序积分提现到银行卡
|
||||||
|
*/
|
||||||
|
@PostMapping("/points")
|
||||||
|
@Operation(summary = "微信小程序积分提现到银行卡", description = "参数:无, 权限:所有人, 方法名:getQrcode")
|
||||||
|
public BaseResponse<Boolean> pointsWithdrawnToBankCard(HttpServletRequest request) throws IOException {
|
||||||
|
Map<String, Object> param = new HashMap<>();
|
||||||
|
param.put("mch_id", "1700326544");
|
||||||
|
param.put("partner_trade_no", OrderNumberUtils.generateOrderId());
|
||||||
|
param.put("nonce_str", "fbemuj4Xql7CYlQJAoTEPYxvPSNgYT2t");
|
||||||
|
param.put("sign", "");
|
||||||
|
param.put("enc_bank_no", "6222031207006363442");
|
||||||
|
param.put("enc_true_name", "陈新知");
|
||||||
|
param.put("bank_code", "1002");
|
||||||
|
param.put("amount", 5);
|
||||||
|
param.put("desc", "提现");
|
||||||
|
String url = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
|
||||||
|
String jsonParams = JSONUtil.toJsonStr(param);
|
||||||
|
String response = HttpUtil.createPost(url)
|
||||||
|
.header("Content-Type", "application/json")
|
||||||
|
.body(jsonParams)
|
||||||
|
.execute()
|
||||||
|
.body();
|
||||||
|
|
||||||
|
return ResultUtils.success(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.greenorange.promotion.service.wechat;
|
||||||
|
|
||||||
|
import com.greenorange.promotion.config.WxAccessToken;
|
||||||
|
|
||||||
|
public interface WechatGetQrcodeService {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取微信token
|
||||||
|
*/
|
||||||
|
WxAccessToken getAccessToken();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.greenorange.promotion.service.wechat.impl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
import cn.hutool.http.HttpUtil;
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.greenorange.promotion.config.WxAccessToken;
|
||||||
|
import com.greenorange.promotion.service.wechat.WechatGetQrcodeService;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.data.redis.core.RedisTemplate;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class WechatGetQrcodeServiceImpl implements WechatGetQrcodeService {
|
||||||
|
|
||||||
|
|
||||||
|
private final static String ACCESS_TOKEN_KEY = "accessToken";
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RedisTemplate<String, Object> redisTemplate;
|
||||||
|
|
||||||
|
|
||||||
|
@Schema(description = "小程序 appId")
|
||||||
|
@Value("${wx.mini.appId}")
|
||||||
|
private String appId;
|
||||||
|
|
||||||
|
@Schema(description = "小程序 appSecret")
|
||||||
|
@Value("${wx.mini.appSecret}")
|
||||||
|
private String appSecret;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取接口调用凭据
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public WxAccessToken getAccessToken() {
|
||||||
|
String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=" + appId + "&secret=" + appSecret;
|
||||||
|
String response = null;
|
||||||
|
try {
|
||||||
|
response = HttpUtil.get(url);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
Gson gson = new Gson();
|
||||||
|
WxAccessToken wxAccessToken = gson.fromJson(response, WxAccessToken.class);
|
||||||
|
String access_token = wxAccessToken.getAccess_token();
|
||||||
|
redisTemplate.opsForValue().set(ACCESS_TOKEN_KEY, access_token, 7200, TimeUnit.SECONDS);
|
||||||
|
return wxAccessToken;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.greenorange.promotion.utils;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
|
public class OrderNumberUtils {
|
||||||
|
|
||||||
|
|
||||||
|
// 定义日期格式化器,精确到秒
|
||||||
|
private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
|
||||||
|
// 定义序列号最大值
|
||||||
|
private static final int MAX_SEQUENCE = 999999;
|
||||||
|
|
||||||
|
// 当前日期,初始化为当天
|
||||||
|
private static String currentDate = getCurrentDate();
|
||||||
|
|
||||||
|
// 自增序列号,线程安全
|
||||||
|
private static final AtomicInteger sequence = new AtomicInteger(0);
|
||||||
|
|
||||||
|
// 锁对象,用于保护自增序列号的生成
|
||||||
|
private static final Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
|
|
||||||
|
public static String generateOrderId() {
|
||||||
|
// 获取当前日期
|
||||||
|
String today = getCurrentDate();
|
||||||
|
|
||||||
|
// 如果日期发生变化,重置序列号
|
||||||
|
if (!today.equals(currentDate)) {
|
||||||
|
currentDate = today;
|
||||||
|
sequence.set(0); // 重置序列号
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取时间戳(精确到秒)
|
||||||
|
String timestamp = DATE_FORMAT.format(new Date());
|
||||||
|
|
||||||
|
// 获取4位随机数
|
||||||
|
String randomNumber = generateRandomNumber();
|
||||||
|
|
||||||
|
// 获取6位自增序列号,并确保不超过最大值
|
||||||
|
int seq = getNextSequence();
|
||||||
|
|
||||||
|
// 格式化序列号为6位
|
||||||
|
String formattedSequence = String.format("%06d", seq);
|
||||||
|
|
||||||
|
// 拼接生成订单号
|
||||||
|
return timestamp + randomNumber + formattedSequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取当前日期(格式:yyyyMMdd)
|
||||||
|
private static String getCurrentDate() {
|
||||||
|
return new SimpleDateFormat("yyyyMMdd").format(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 生成4位随机数(范围:0000到9999)
|
||||||
|
private static String generateRandomNumber() {
|
||||||
|
int random = (int) (Math.random() * 10000); // 生成0到9999之间的随机数
|
||||||
|
return String.format("%04d", random); // 格式化为4位
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取下一个自增序列号,使用ReentrantLock来确保线程安全
|
||||||
|
private static int getNextSequence() {
|
||||||
|
lock.lock(); // 获取锁
|
||||||
|
try {
|
||||||
|
int seq = sequence.incrementAndGet();
|
||||||
|
if (seq > MAX_SEQUENCE) {
|
||||||
|
sequence.set(0); // 达到最大值后重置
|
||||||
|
seq = sequence.incrementAndGet();
|
||||||
|
}
|
||||||
|
return seq;
|
||||||
|
} finally {
|
||||||
|
lock.unlock(); // 确保在最终释放锁
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
131
src/main/java/com/greenorange/promotion/utils/QRCodeUtil.java
Normal file
131
src/main/java/com/greenorange/promotion/utils/QRCodeUtil.java
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
package com.greenorange.promotion.utils;
|
||||||
|
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.geom.Ellipse2D;
|
||||||
|
import java.awt.geom.RoundRectangle2D;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
public class QRCodeUtil {
|
||||||
|
|
||||||
|
|
||||||
|
// 将InputStream转换为BufferedImage
|
||||||
|
public static BufferedImage inputStreamToBufferedImage(InputStream inputStream) throws IOException {
|
||||||
|
return ImageIO.read(inputStream);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取用户头像并缩放到指定大小
|
||||||
|
public static BufferedImage getScaledAvatar(String url, int targetWidth, int targetHeight) throws IOException {
|
||||||
|
BufferedImage avatarImage = ImageIO.read(new URL(url));
|
||||||
|
int width = avatarImage.getWidth();
|
||||||
|
int height = avatarImage.getHeight();
|
||||||
|
|
||||||
|
// 如果头像大于目标大小,进行缩放
|
||||||
|
if (width > targetWidth && height > targetHeight) {
|
||||||
|
width = targetWidth;
|
||||||
|
height = targetHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
return toBufferedImage(avatarImage.getScaledInstance(width, height, Image.SCALE_DEFAULT));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将Image转换为BufferedImage
|
||||||
|
public static BufferedImage toBufferedImage(Image image) {
|
||||||
|
if (image instanceof BufferedImage) {
|
||||||
|
return (BufferedImage) image;
|
||||||
|
}
|
||||||
|
BufferedImage bimage = new BufferedImage(image.getWidth(null), image.getHeight(null), BufferedImage.TYPE_INT_RGB);
|
||||||
|
Graphics g = bimage.createGraphics();
|
||||||
|
g.drawImage(image, 0, 0, null);
|
||||||
|
g.dispose();
|
||||||
|
return bimage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// // 将图片转为圆形
|
||||||
|
// public static BufferedImage getCircularImage(BufferedImage img) {
|
||||||
|
// int width = img.getWidth();
|
||||||
|
// int height = img.getHeight();
|
||||||
|
// BufferedImage circularImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||||
|
// Graphics2D g = circularImage.createGraphics();
|
||||||
|
// Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, width, height);
|
||||||
|
// g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
// g.setClip(shape);
|
||||||
|
// g.drawImage(img, 0, 0, null);
|
||||||
|
// g.dispose();
|
||||||
|
// return circularImage;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将图片裁剪成圆形,并确保背景透明
|
||||||
|
* @param img 原始图片
|
||||||
|
* @return 裁剪后的圆形图片,背景为透明
|
||||||
|
*/
|
||||||
|
public static BufferedImage getCircularImage(BufferedImage img) {
|
||||||
|
int width = img.getWidth();
|
||||||
|
int height = img.getHeight();
|
||||||
|
|
||||||
|
// 创建一个透明背景的 BufferedImage
|
||||||
|
BufferedImage circularImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
|
||||||
|
|
||||||
|
Graphics2D g = circularImage.createGraphics();
|
||||||
|
Ellipse2D.Double shape = new Ellipse2D.Double(0, 0, width, height);
|
||||||
|
|
||||||
|
g.setComposite(AlphaComposite.Src);
|
||||||
|
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
g.setColor(Color.WHITE);
|
||||||
|
g.fill(shape);
|
||||||
|
g.setComposite(AlphaComposite.SrcAtop);
|
||||||
|
g.drawImage(img, 0, 0, null);
|
||||||
|
g.dispose();
|
||||||
|
|
||||||
|
return circularImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 合并二维码和头像
|
||||||
|
public static BufferedImage addImages(BufferedImage qrImage, BufferedImage avatarImage, int x, int y) {
|
||||||
|
Graphics2D g = qrImage.createGraphics();
|
||||||
|
g.drawImage(avatarImage, x, y, avatarImage.getWidth(), avatarImage.getHeight(), null);
|
||||||
|
g.dispose();
|
||||||
|
return qrImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 合并二维码和空白图片
|
||||||
|
public static BufferedImage addBlankImage(BufferedImage qrImage, BufferedImage blankImage, int x, int y) {
|
||||||
|
Graphics2D g = qrImage.createGraphics();
|
||||||
|
g.drawImage(blankImage, x, y, blankImage.getWidth(), blankImage.getHeight(), null);
|
||||||
|
g.dispose();
|
||||||
|
return qrImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将BufferedImage转换为InputStream
|
||||||
|
public static InputStream bufferedImageToInputStream(BufferedImage image) throws IOException {
|
||||||
|
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||||
|
ImageIO.write(image, "png", os);
|
||||||
|
return new ByteArrayInputStream(os.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加文字到图片上
|
||||||
|
public static BufferedImage addTextToImage(BufferedImage image, String text, Color color, Font font, int x, int y) {
|
||||||
|
Graphics2D g = image.createGraphics();
|
||||||
|
g.setColor(color);
|
||||||
|
g.setFont(font);
|
||||||
|
g.drawString(text, x, y);
|
||||||
|
g.dispose();
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存图片到文件
|
||||||
|
public static void saveImageToFile(BufferedImage image, String path) throws IOException {
|
||||||
|
File outputfile = new File(path);
|
||||||
|
ImageIO.write(image, "png", outputfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,64 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.security.GeneralSecurityException;
|
||||||
|
import java.security.InvalidAlgorithmParameterException;
|
||||||
|
import java.security.InvalidKeyException;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.NoSuchPaddingException;
|
||||||
|
import javax.crypto.spec.GCMParameterSpec;
|
||||||
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
||||||
|
public class AesUtil {
|
||||||
|
static final int KEY_LENGTH_BYTE = 32;
|
||||||
|
static final int TAG_LENGTH_BIT = 128;
|
||||||
|
private final byte[] aesKey;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建解密类
|
||||||
|
*
|
||||||
|
* @param key
|
||||||
|
*/
|
||||||
|
public AesUtil(byte[] key) {
|
||||||
|
if (key.length != KEY_LENGTH_BYTE) {
|
||||||
|
throw new IllegalArgumentException("无效的ApiV3Key,长度必须为32个字节");
|
||||||
|
}
|
||||||
|
this.aesKey = key;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解密数据
|
||||||
|
*
|
||||||
|
* @param associatedData
|
||||||
|
* 附加数据包
|
||||||
|
* @param nonce
|
||||||
|
* 加密使用的随机串初始化向量
|
||||||
|
* @param ciphertext
|
||||||
|
* Base64编码后的密文
|
||||||
|
* @return
|
||||||
|
* @throws GeneralSecurityException
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public String decryptToString(byte[] associatedData, byte[] nonce, String ciphertext)
|
||||||
|
throws GeneralSecurityException, IOException {
|
||||||
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
|
||||||
|
|
||||||
|
SecretKeySpec key = new SecretKeySpec(aesKey, "AES");
|
||||||
|
GCMParameterSpec spec = new GCMParameterSpec(TAG_LENGTH_BIT, nonce);
|
||||||
|
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, key, spec);
|
||||||
|
cipher.updateAAD(associatedData);
|
||||||
|
|
||||||
|
return new String(cipher.doFinal(Base64.getDecoder().decode(ciphertext)), "utf-8");
|
||||||
|
} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
} catch (InvalidKeyException | InvalidAlgorithmParameterException e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class CompanyWxPayBankBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private static String sendUrl = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
|
||||||
|
|
||||||
|
private String certPath, API_KEY, mch_id, nonce_str, partner_trade_no, desc, sign, enc_bank_no, enc_true_name,
|
||||||
|
bank_code, enc_bank_no_pwd, enc_true_name_pwd;
|
||||||
|
private String pub_key;
|
||||||
|
private int amount;
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public CompanyWxPayBankBuilder(String certPath, String pub_key) {
|
||||||
|
nonce_str = WxPayUtil.getRandomStr(20);
|
||||||
|
int startIndex = pub_key.indexOf("-----BEGIN RSA PUBLIC KEY-----");
|
||||||
|
int endIndex = pub_key.indexOf("-----END RSA PUBLIC KEY-----");
|
||||||
|
this.pub_key = pub_key;
|
||||||
|
|
||||||
|
if (startIndex >= 0 && endIndex >= 0) {
|
||||||
|
this.pub_key = pub_key.substring(startIndex + "-----BEGIN RSA PUBLIC KEY-----".length(), endIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.certPath = certPath;
|
||||||
|
partner_trade_no = System.currentTimeMillis() + WxPayUtil.getRandomStr(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(int amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
CompanyWxPayBankBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCertPath() {
|
||||||
|
return certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertPath(String certPath) {
|
||||||
|
this.certPath = certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAPI_KEY() {
|
||||||
|
return API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAPI_KEY(String aPI_KEY) {
|
||||||
|
API_KEY = aPI_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getmch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setmch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNonce_str() {
|
||||||
|
return nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonce_str(String nonce_str) {
|
||||||
|
this.nonce_str = nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPartner_trade_no() {
|
||||||
|
return partner_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPartner_trade_no(String partner_trade_no) {
|
||||||
|
this.partner_trade_no = partner_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDesc(String desc) {
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnc_bank_no() {
|
||||||
|
return enc_bank_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnc_bank_no(String enc_bank_no) {
|
||||||
|
try {
|
||||||
|
enc_bank_no_pwd = RSAEncryp.encrypt(enc_bank_no.getBytes("utf-8"), pub_key, 11,
|
||||||
|
"RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
enc_bank_no_pwd = "";
|
||||||
|
}
|
||||||
|
this.enc_bank_no = enc_bank_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnc_true_name() {
|
||||||
|
return enc_true_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEnc_true_name(String enc_true_name) {
|
||||||
|
try {
|
||||||
|
enc_true_name_pwd = RSAEncryp.encrypt(enc_true_name.getBytes("utf-8"), pub_key, 11,
|
||||||
|
"RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING");
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
enc_true_name_pwd = "";
|
||||||
|
}
|
||||||
|
this.enc_true_name = enc_true_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBank_code() {
|
||||||
|
return bank_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBank_code(String bank_code) {
|
||||||
|
this.bank_code = bank_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
reStringBuffer.append("<xml>");
|
||||||
|
appendParam("amount", amount + "", true);
|
||||||
|
appendParam("bank_code", bank_code + "", true);
|
||||||
|
appendParam("desc", desc, true);
|
||||||
|
appendParam("enc_bank_no", enc_bank_no_pwd, true);
|
||||||
|
appendParam("enc_true_name", enc_true_name_pwd, true);
|
||||||
|
appendParam("mch_id", mch_id, true);
|
||||||
|
appendParam("nonce_str", nonce_str, true);
|
||||||
|
appendParam("partner_trade_no", partner_trade_no, true);
|
||||||
|
getSign(API_KEY, this.signStringBuffer.toString());
|
||||||
|
appendParam("sign", sign, true);
|
||||||
|
reStringBuffer.append("</xml>");
|
||||||
|
build = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certPath == null || certPath.length() == 0) {
|
||||||
|
throw new LackParamExceptions("未设置证书路径");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pub_key == null || pub_key.length() == 0) {
|
||||||
|
throw new LackParamExceptions("未设置公钥");
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
JSONObject resultJson = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
result = WxPayUtil.doPostDataWithCert(sendUrl, reStringBuffer.toString(), mch_id, certPath);
|
||||||
|
|
||||||
|
Map<String, String> getResult = WxPayUtil.xmlToMap(result);
|
||||||
|
if (getResult.get("result_code") == null || !"SUCCESS".equalsIgnoreCase(getResult.get("result_code"))) {
|
||||||
|
resultJson.put("return_code", "FAIL");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
} else {
|
||||||
|
resultJson.put("return_code", "SUCCESS");
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("amount", getResult.get("amount"));
|
||||||
|
resultJson.put("payment_no", getResult.get("payment_no"));
|
||||||
|
resultJson.put("cmms_amt", getResult.get("cmms_amt"));
|
||||||
|
resultJson.put("partner_trade_no", getResult.get("partner_trade_no"));
|
||||||
|
resultJson.put("nonce_str", getResult.get("nonce_str"));
|
||||||
|
resultJson.put("mch_id", getResult.get("mch_id"));
|
||||||
|
resultJson.put("mch_appid", getResult.get("mch_appid"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSign(String apikey, String value) throws LackParamExceptions {
|
||||||
|
if (apikey == null) {
|
||||||
|
throw new LackParamExceptions("商户号API秘钥不能为空");
|
||||||
|
} else {
|
||||||
|
sign = WxPayUtil.MD5(signStringBuffer.toString() + "key=" + apikey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null || value.length() == 0) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append("<" + key + ">");
|
||||||
|
this.reStringBuffer.append("<![CDATA[" + value + "]]>");
|
||||||
|
this.reStringBuffer.append("</" + key + ">");
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,169 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class CompanyWxPayBankQueryBuilder implements WxPayDataBuilder {
|
||||||
|
private static String sendUrl = "https://api.mch.weixin.qq.com/mmpaysptrans/query_bank";
|
||||||
|
|
||||||
|
private String certPath, API_KEY, mch_id, nonce_str, partner_trade_no, sign;
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public CompanyWxPayBankQueryBuilder(String certPath, String partner_trade_no) {
|
||||||
|
nonce_str = WxPayUtil.getRandomStr(20);
|
||||||
|
this.certPath = certPath;
|
||||||
|
this.partner_trade_no = partner_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
CompanyWxPayBankQueryBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCertPath() {
|
||||||
|
return certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertPath(String certPath) {
|
||||||
|
this.certPath = certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAPI_KEY() {
|
||||||
|
return API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAPI_KEY(String aPI_KEY) {
|
||||||
|
API_KEY = aPI_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getmch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setmch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNonce_str() {
|
||||||
|
return nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonce_str(String nonce_str) {
|
||||||
|
this.nonce_str = nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPartner_trade_no() {
|
||||||
|
return partner_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPartner_trade_no(String partner_trade_no) {
|
||||||
|
this.partner_trade_no = partner_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
reStringBuffer.append("<xml>");
|
||||||
|
appendParam("mch_id", mch_id, true);
|
||||||
|
appendParam("nonce_str", nonce_str, true);
|
||||||
|
appendParam("partner_trade_no", partner_trade_no, true);
|
||||||
|
getSign(API_KEY, this.signStringBuffer.toString());
|
||||||
|
appendParam("sign", sign, true);
|
||||||
|
reStringBuffer.append("</xml>");
|
||||||
|
build = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certPath == null || certPath.length() == 0) {
|
||||||
|
throw new LackParamExceptions("未设置证书路径");
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
JSONObject resultJson = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
result = WxPayUtil.doPostDataWithCert(sendUrl, reStringBuffer.toString(), mch_id, certPath);
|
||||||
|
|
||||||
|
Map<String, String> getResult = WxPayUtil.xmlToMap(result);
|
||||||
|
if (getResult.get("result_code") == null || !"SUCCESS".equalsIgnoreCase(getResult.get("result_code"))) {
|
||||||
|
resultJson.put("return_code", "FAIL");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
} else {
|
||||||
|
resultJson.put("return_code", "SUCCESS");
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("amount", getResult.get("amount"));
|
||||||
|
resultJson.put("payment_no", getResult.get("payment_no"));
|
||||||
|
resultJson.put("cmms_amt", getResult.get("cmms_amt"));
|
||||||
|
resultJson.put("partner_trade_no", getResult.get("partner_trade_no"));
|
||||||
|
resultJson.put("nonce_str", getResult.get("nonce_str"));
|
||||||
|
resultJson.put("mch_id", getResult.get("mch_id"));
|
||||||
|
resultJson.put("mch_appid", getResult.get("mch_appid"));
|
||||||
|
resultJson.put("status", getResult.get("status"));
|
||||||
|
resultJson.put("create_time", getResult.get("create_time"));
|
||||||
|
resultJson.put("reason", getResult.get("reason"));
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSign(String apikey, String value) throws LackParamExceptions {
|
||||||
|
if (apikey == null) {
|
||||||
|
throw new LackParamExceptions("商户号API秘钥不能为空");
|
||||||
|
} else {
|
||||||
|
sign = WxPayUtil.MD5(signStringBuffer.toString() + "key=" + apikey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null || value.length() == 0) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append("<" + key + ">");
|
||||||
|
this.reStringBuffer.append("<![CDATA[" + value + "]]>");
|
||||||
|
this.reStringBuffer.append("</" + key + ">");
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,234 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class CompanyWxPayBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private static String sendUrl = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
|
||||||
|
|
||||||
|
private String certPath, API_KEY, mch_appid, mchid, nonce_str, partner_trade_no, desc, check_name, spbill_create_ip,
|
||||||
|
openid, device_info, re_user_name, sign;
|
||||||
|
|
||||||
|
private int amount;
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public CompanyWxPayBuilder(String certPath) {
|
||||||
|
nonce_str = WxPayUtil.getRandomStr(20);
|
||||||
|
this.certPath = certPath;
|
||||||
|
// 默认订单时间为半小时内有效
|
||||||
|
partner_trade_no = System.currentTimeMillis() + WxPayUtil.getRandomStr(8);
|
||||||
|
check_name = "NO_CHECK";
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getAmount() {
|
||||||
|
return amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAmount(int amount) {
|
||||||
|
this.amount = amount;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
CompanyWxPayBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCertPath() {
|
||||||
|
return certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertPath(String certPath) {
|
||||||
|
this.certPath = certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAPI_KEY() {
|
||||||
|
return API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAPI_KEY(String aPI_KEY) {
|
||||||
|
API_KEY = aPI_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMch_appid() {
|
||||||
|
return mch_appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMch_appid(String mch_appid) {
|
||||||
|
this.mch_appid = mch_appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMchid() {
|
||||||
|
return mchid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMchid(String mchid) {
|
||||||
|
this.mchid = mchid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNonce_str() {
|
||||||
|
return nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonce_str(String nonce_str) {
|
||||||
|
this.nonce_str = nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPartner_trade_no() {
|
||||||
|
return partner_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPartner_trade_no(String partner_trade_no) {
|
||||||
|
this.partner_trade_no = partner_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDesc() {
|
||||||
|
return desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDesc(String desc) {
|
||||||
|
this.desc = desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCheck_name() {
|
||||||
|
return check_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCheck_name(String check_name) {
|
||||||
|
this.check_name = check_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpbill_create_ip() {
|
||||||
|
return spbill_create_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpbill_create_ip(String spbill_create_ip) {
|
||||||
|
this.spbill_create_ip = spbill_create_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpenid() {
|
||||||
|
return openid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenid(String openid) {
|
||||||
|
this.openid = openid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDevice_info() {
|
||||||
|
return device_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevice_info(String device_info) {
|
||||||
|
this.device_info = device_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRe_user_name() {
|
||||||
|
return re_user_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRe_user_name(String re_user_name) {
|
||||||
|
this.re_user_name = re_user_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
reStringBuffer.append("<xml>");
|
||||||
|
appendParam("amount", amount + "", true);
|
||||||
|
appendParam("check_name", check_name, true);
|
||||||
|
appendParam("desc", desc, true);
|
||||||
|
appendParam("device_info", device_info, false);
|
||||||
|
appendParam("mch_appid", mch_appid, true);
|
||||||
|
appendParam("mchid", mchid, true);
|
||||||
|
appendParam("nonce_str", nonce_str, true);
|
||||||
|
appendParam("openid", openid, true);
|
||||||
|
appendParam("partner_trade_no", partner_trade_no, true);
|
||||||
|
appendParam("re_user_name", re_user_name, false);
|
||||||
|
appendParam("spbill_create_ip", spbill_create_ip, true);
|
||||||
|
|
||||||
|
getSign(API_KEY, this.signStringBuffer.toString());
|
||||||
|
|
||||||
|
appendParam("sign", sign, true);
|
||||||
|
reStringBuffer.append("</xml>");
|
||||||
|
build = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certPath == null || certPath.length() == 0) {
|
||||||
|
throw new LackParamExceptions("未设置证书路径");
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
JSONObject resultJson = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = WxPayUtil.doPostDataWithCert(sendUrl, reStringBuffer.toString(), mchid, certPath);
|
||||||
|
|
||||||
|
Map<String, String> getResult = WxPayUtil.xmlToMap(result);
|
||||||
|
if (getResult.get("result_code") == null || !"SUCCESS".equalsIgnoreCase(getResult.get("result_code"))) {
|
||||||
|
resultJson.put("return_code", "FAIL");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
} else {
|
||||||
|
resultJson.put("return_code", "SUCCESS");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("payment_time", getResult.get("payment_time"));
|
||||||
|
resultJson.put("payment_no", getResult.get("payment_no"));
|
||||||
|
resultJson.put("partner_trade_no", getResult.get("partner_trade_no"));
|
||||||
|
resultJson.put("nonce_str", getResult.get("nonce_str"));
|
||||||
|
resultJson.put("mchid", getResult.get("mchid"));
|
||||||
|
resultJson.put("mch_appid", getResult.get("mch_appid"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSign(String apikey, String value) throws LackParamExceptions {
|
||||||
|
if (apikey == null) {
|
||||||
|
throw new LackParamExceptions("商户号API秘钥不能为空");
|
||||||
|
} else {
|
||||||
|
sign = WxPayUtil.MD5(signStringBuffer.toString() + "key=" + apikey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append("<" + key + ">");
|
||||||
|
this.reStringBuffer.append("<![CDATA[" + value + "]]>");
|
||||||
|
this.reStringBuffer.append("</" + key + ">");
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,180 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
public class EasyPayBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private static String sendUrl = "http://pay2.w-x.net.cn/Pay/PlaceOrder";
|
||||||
|
private static String sendUrl2 = "http://api.sczsgc.cn/Pay/PlaceOrder";
|
||||||
|
|
||||||
|
private String notify_url, return_url, orderid, orderuid, goodsname, key, token;
|
||||||
|
|
||||||
|
private int uid, istype;
|
||||||
|
|
||||||
|
private float price;
|
||||||
|
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public EasyPayBuilder() {
|
||||||
|
orderid = System.currentTimeMillis() + WxPayUtil.getRandomStr(8);
|
||||||
|
orderuid = System.currentTimeMillis() + WxPayUtil.getRandomStr(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getToken() {
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setToken(String token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotify_url() {
|
||||||
|
return notify_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotify_url(String notify_url) {
|
||||||
|
this.notify_url = notify_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReturn_url() {
|
||||||
|
return return_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReturn_url(String return_url) {
|
||||||
|
this.return_url = return_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrderid() {
|
||||||
|
return orderid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderid(String orderid) {
|
||||||
|
this.orderid = orderid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrderuid() {
|
||||||
|
return orderuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrderuid(String orderuid) {
|
||||||
|
this.orderuid = orderuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGoodsname() {
|
||||||
|
return goodsname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoodsname(String goodsname) {
|
||||||
|
this.goodsname = goodsname;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKey(String key) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getUid() {
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUid(int uid) {
|
||||||
|
this.uid = uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIstype() {
|
||||||
|
return istype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIstype(int istype) {
|
||||||
|
this.istype = istype;
|
||||||
|
}
|
||||||
|
|
||||||
|
public float getPrice() {
|
||||||
|
return price;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPrice(float price) {
|
||||||
|
this.price = price;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
appendParam("goodsname", goodsname, true);
|
||||||
|
appendParam("istype", istype + "", true);
|
||||||
|
appendParam("notify_url", notify_url, true);
|
||||||
|
appendParam("orderid", orderid, true);
|
||||||
|
appendParam("orderuid", orderuid, false);
|
||||||
|
appendParam("price", price + "", true);
|
||||||
|
appendParam("return_url", return_url, true);
|
||||||
|
|
||||||
|
if (token == null) {
|
||||||
|
throw new LackParamExceptions("参数token不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
signStringBuffer.append(token);
|
||||||
|
|
||||||
|
appendParam("uid", uid + "", true);
|
||||||
|
|
||||||
|
key = WxPayUtil.MD5(signStringBuffer.toString());
|
||||||
|
|
||||||
|
appendParam("key", key, true);
|
||||||
|
|
||||||
|
build = true;
|
||||||
|
|
||||||
|
System.out.println(reStringBuffer.toString());
|
||||||
|
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
// 正常的域名
|
||||||
|
result = WxPayUtil.sendHttpRequest(sendUrl, reStringBuffer.toString(), "application/x-www-form-urlencoded",
|
||||||
|
"utf-8", "POST");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// 备用域名
|
||||||
|
try {
|
||||||
|
result = WxPayUtil.sendHttpRequest(sendUrl2, reStringBuffer.toString(),
|
||||||
|
"application/x-www-form-urlencoded", "utf-8", "POST");
|
||||||
|
} catch (IOException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
throw new LackParamExceptions(e1.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println(result);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.reStringBuffer.append(key + "=" + value + "&");
|
||||||
|
this.signStringBuffer.append(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class GetOpenidBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private String appid, appsecret, code;
|
||||||
|
private static String sendUrl = "https://api.weixin.qq.com/sns/oauth2/access_token";
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
GetOpenidBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppid() {
|
||||||
|
return appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppid(String appid) {
|
||||||
|
this.appid = appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppsecret() {
|
||||||
|
return appsecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppsecret(String appsecret) {
|
||||||
|
this.appsecret = appsecret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCode() {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCode(String code) {
|
||||||
|
this.code = code;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
appendParam("appid", appid, true);
|
||||||
|
appendParam("secret", appsecret, true);
|
||||||
|
appendParam("code", code, true);
|
||||||
|
appendParam("grant_type", "authorization_code", true);
|
||||||
|
reStringBuffer.deleteCharAt(reStringBuffer.length() - 1);
|
||||||
|
build = true;
|
||||||
|
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
JSONObject jsonObject = null;
|
||||||
|
try {
|
||||||
|
// 正常是的域名
|
||||||
|
result = WxPayUtil.sendHttpsRequest(sendUrl, reStringBuffer.toString(), "text/xml", "utf-8", "GET");
|
||||||
|
jsonObject = JSONObject.fromObject(result);
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// 备用域名
|
||||||
|
throw new LackParamExceptions(e.toString());
|
||||||
|
}
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class GetPublicKeyBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private static String sendUrl = "https://fraud.mch.weixin.qq.com/risk/getpublickey";
|
||||||
|
|
||||||
|
private String certPath, API_KEY, mch_id, nonce_str, sign;
|
||||||
|
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public GetPublicKeyBuilder(String certPath) {
|
||||||
|
nonce_str = WxPayUtil.getRandomStr(20);
|
||||||
|
this.certPath = certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
GetPublicKeyBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCertPath() {
|
||||||
|
return certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertPath(String certPath) {
|
||||||
|
this.certPath = certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAPI_KEY() {
|
||||||
|
return API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAPI_KEY(String aPI_KEY) {
|
||||||
|
API_KEY = aPI_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getmch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setmch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNonce_str() {
|
||||||
|
return nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonce_str(String nonce_str) {
|
||||||
|
this.nonce_str = nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
reStringBuffer.append("<xml>");
|
||||||
|
appendParam("mch_id", mch_id, true);
|
||||||
|
appendParam("nonce_str", nonce_str, true);
|
||||||
|
getSign(API_KEY, this.signStringBuffer.toString());
|
||||||
|
appendParam("sign", sign, true);
|
||||||
|
reStringBuffer.append("</xml>");
|
||||||
|
build = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("null")
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (certPath == null || certPath.length() == 0) {
|
||||||
|
throw new LackParamExceptions("未设置证书路径");
|
||||||
|
}
|
||||||
|
|
||||||
|
String result = "";
|
||||||
|
JSONObject resultJson = new JSONObject();
|
||||||
|
|
||||||
|
try {
|
||||||
|
result = WxPayUtil.httpClientResultGetPublicKey(sendUrl, reStringBuffer.toString(), mch_id, certPath);
|
||||||
|
Map<String, String> getResult = WxPayUtil.xmlToMap(result);
|
||||||
|
if (getResult.get("result_code") == null || !"SUCCESS".equalsIgnoreCase(getResult.get("result_code"))) {
|
||||||
|
resultJson.put("return_code", "FAIL");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
} else {
|
||||||
|
resultJson.put("return_code", "SUCCESS");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("mch_id", getResult.get("mch_id"));
|
||||||
|
resultJson.put("pub_key", getResult.get("pub_key"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSign(String apikey, String value) throws LackParamExceptions {
|
||||||
|
if (apikey == null) {
|
||||||
|
throw new LackParamExceptions("商户号API秘钥不能为空");
|
||||||
|
} else {
|
||||||
|
sign = WxPayUtil.MD5(signStringBuffer.toString() + "key=" + apikey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append("<" + key + ">");
|
||||||
|
this.reStringBuffer.append("<![CDATA[" + value + "]]>");
|
||||||
|
this.reStringBuffer.append("</" + key + ">");
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,331 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class JSAPIWxPayBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private static String sendUrl = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||||
|
private static String sendUrl2 = "https://api2.mch.weixin.qq.com/pay/unifiedorder";
|
||||||
|
|
||||||
|
private String appid, mch_id, body, out_trade_no, device_info, sign, detail, attach, time_start, time_expire,
|
||||||
|
goods_tag, product_id, spbill_create_ip, notify_url, limit_pay, openid, receipt, scene_info, API_KEY,
|
||||||
|
nonce_str;
|
||||||
|
|
||||||
|
private int total_fee;
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public JSAPIWxPayBuilder() {
|
||||||
|
nonce_str = WxPayUtil.getRandomStr(20);
|
||||||
|
// 默认订单时间为半小时内有效
|
||||||
|
time_start = WxPayUtil.FormatDate(System.currentTimeMillis());
|
||||||
|
time_expire = WxPayUtil.FormatDate(System.currentTimeMillis() + 30 * 60 * 1000);
|
||||||
|
|
||||||
|
out_trade_no = System.currentTimeMillis() + WxPayUtil.getRandomStr(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
JSAPIWxPayBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl2() {
|
||||||
|
return sendUrl2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl2(String sendUrl2) {
|
||||||
|
JSAPIWxPayBuilder.sendUrl2 = sendUrl2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAPI_KEY() {
|
||||||
|
return API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAPI_KEY(String aPI_KEY) {
|
||||||
|
API_KEY = aPI_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppid() {
|
||||||
|
return appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppid(String appid) {
|
||||||
|
this.appid = appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBody(String body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOut_trade_no() {
|
||||||
|
return out_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOut_trade_no(String out_trade_no) {
|
||||||
|
this.out_trade_no = out_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDevice_info() {
|
||||||
|
return device_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDevice_info(String device_info) {
|
||||||
|
this.device_info = device_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDetail() {
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDetail(String detail) {
|
||||||
|
this.detail = detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAttach() {
|
||||||
|
return attach;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAttach(String attach) {
|
||||||
|
this.attach = attach;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTime_start() {
|
||||||
|
return time_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime_start(String time_start) {
|
||||||
|
this.time_start = time_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTime_expire() {
|
||||||
|
return time_expire;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTime_expire(String time_expire) {
|
||||||
|
this.time_expire = time_expire;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGoods_tag() {
|
||||||
|
return goods_tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoods_tag(String goods_tag) {
|
||||||
|
this.goods_tag = goods_tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProduct_id() {
|
||||||
|
return product_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProduct_id(String product_id) {
|
||||||
|
this.product_id = product_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSpbill_create_ip() {
|
||||||
|
return spbill_create_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpbill_create_ip(String spbill_create_ip) {
|
||||||
|
this.spbill_create_ip = spbill_create_ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotify_url() {
|
||||||
|
return notify_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotify_url(String notify_url) {
|
||||||
|
this.notify_url = notify_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLimit_pay() {
|
||||||
|
return limit_pay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLimit_pay(String limit_pay) {
|
||||||
|
this.limit_pay = limit_pay;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOpenid() {
|
||||||
|
return openid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpenid(String openid) {
|
||||||
|
this.openid = openid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReceipt() {
|
||||||
|
return receipt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReceipt(String receipt) {
|
||||||
|
this.receipt = receipt;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScene_info() {
|
||||||
|
return scene_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScene_info(String scene_info) {
|
||||||
|
this.scene_info = scene_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotal_fee() {
|
||||||
|
return total_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal_fee(int total_fee) {
|
||||||
|
this.total_fee = total_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
reStringBuffer.append("<xml>");
|
||||||
|
appendParam("appid", appid, true);
|
||||||
|
appendParam("attach", attach, false);
|
||||||
|
appendParam("body", body, true);
|
||||||
|
appendParam("detail", detail, false);
|
||||||
|
appendParam("device_info", device_info, false);
|
||||||
|
appendParam("goods_tag", goods_tag, false);
|
||||||
|
appendParam("limit_pay", limit_pay, false);
|
||||||
|
appendParam("mch_id", mch_id, true);
|
||||||
|
appendParam("nonce_str", nonce_str, true);
|
||||||
|
appendParam("notify_url", notify_url, true);
|
||||||
|
appendParam("openid", openid, true);
|
||||||
|
appendParam("out_trade_no", out_trade_no, true);
|
||||||
|
appendParam("product_id", product_id, false);
|
||||||
|
appendParam("receipt", receipt, false);
|
||||||
|
appendParam("scene_info", scene_info, false);
|
||||||
|
appendParam("sign_type", "MD5", false);
|
||||||
|
appendParam("spbill_create_ip", spbill_create_ip, true);
|
||||||
|
appendParam("time_expire", time_expire, false);
|
||||||
|
appendParam("time_start", time_start, false);
|
||||||
|
appendParam("total_fee", total_fee + "", true);
|
||||||
|
appendParam("trade_type", "JSAPI", true);
|
||||||
|
|
||||||
|
getSign(API_KEY, this.signStringBuffer.toString());
|
||||||
|
appendParam("sign", sign, true);
|
||||||
|
reStringBuffer.append("</xml>");
|
||||||
|
|
||||||
|
build = true;
|
||||||
|
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSign(String apikey, String value) throws LackParamExceptions {
|
||||||
|
if (apikey == null) {
|
||||||
|
throw new LackParamExceptions("商户号操作秘钥不能为空");
|
||||||
|
} else {
|
||||||
|
|
||||||
|
sign = WxPayUtil.MD5(signStringBuffer.toString() + "key=" + API_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append("<" + key + ">");
|
||||||
|
this.reStringBuffer.append("<![CDATA[" + value + "]]>");
|
||||||
|
this.reStringBuffer.append("</" + key + ">");
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void signAppendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
try {
|
||||||
|
// 正常是的域名
|
||||||
|
result = WxPayUtil.sendHttpsRequest(sendUrl, reStringBuffer.toString(), "text/xml", "utf-8", "POST");
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// 备用域名
|
||||||
|
try {
|
||||||
|
result = WxPayUtil.sendHttpsRequest(sendUrl2, reStringBuffer.toString(), "text/xml", "utf-8", "POST");
|
||||||
|
} catch (IOException e1) {
|
||||||
|
e1.printStackTrace();
|
||||||
|
throw new LackParamExceptions(e1.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> getResult = WxPayUtil.xmlToMap(result);
|
||||||
|
|
||||||
|
JSONObject resultJson = new JSONObject();
|
||||||
|
|
||||||
|
if (getResult.get("result_code") == null || !"SUCCESS".equalsIgnoreCase(getResult.get("result_code"))) {
|
||||||
|
resultJson.put("return_code", "FAIL");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
} else {
|
||||||
|
long curTime = System.currentTimeMillis() / 1000;
|
||||||
|
// 再次签名
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
signAppendParam("appId", appid, true);
|
||||||
|
signAppendParam("nonceStr", getResult.get("nonce_str"), true);
|
||||||
|
signAppendParam("package", "prepay_id=" + getResult.get("prepay_id"), true);
|
||||||
|
signAppendParam("signType", "MD5", true);
|
||||||
|
signAppendParam("timeStamp", curTime + "", true);
|
||||||
|
|
||||||
|
String sign = WxPayUtil.MD5(signStringBuffer.toString() + "key=" + API_KEY);
|
||||||
|
|
||||||
|
resultJson.put("return_code", "SUCCESS");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("nonceStr", getResult.get("nonce_str"));
|
||||||
|
resultJson.put("timeStamp", curTime);
|
||||||
|
resultJson.put("paySign", sign);
|
||||||
|
resultJson.put("package", "prepay_id=" + getResult.get("prepay_id"));
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class LackParamExceptions extends Exception {
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
private static final long serialVersionUID = 3751503410029217326L;
|
||||||
|
|
||||||
|
public LackParamExceptions() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public LackParamExceptions(String agr0) {
|
||||||
|
super(agr0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class MxObjectLockUtil {
|
||||||
|
private HashMap<String, PlanLock> planLockHashMap = new HashMap<>(40);
|
||||||
|
private volatile static MxObjectLockUtil instance;
|
||||||
|
|
||||||
|
private MxObjectLockUtil() throws IllegalAccessException {
|
||||||
|
if (instance != null) {
|
||||||
|
throw new IllegalAccessException("该类为单例模式,不可生成额外的对象");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, PlanLock> getPlanLockHashMap() {
|
||||||
|
return planLockHashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public synchronized PlanLock getObjectLock(String key) {
|
||||||
|
if (planLockHashMap.get(key) == null) {
|
||||||
|
PlanLock planLock = new PlanLock();
|
||||||
|
planLockHashMap.put(key, planLock);
|
||||||
|
return planLock;
|
||||||
|
}
|
||||||
|
return planLockHashMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public PlanLock removeLock(String key) {
|
||||||
|
PlanLock planLock = null;
|
||||||
|
if (planLockHashMap.get(key) != null) {
|
||||||
|
planLock = planLockHashMap.remove(key);
|
||||||
|
}
|
||||||
|
return planLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MxObjectLockUtil getInstance() {
|
||||||
|
if (instance == null) {
|
||||||
|
synchronized (MxObjectLockUtil.class) {
|
||||||
|
if (instance == null) {
|
||||||
|
try {
|
||||||
|
instance = new MxObjectLockUtil();
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class PlanLock {
|
||||||
|
public synchronized void execute(Runnable runnable) {
|
||||||
|
runnable.run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,244 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.security.KeyFactory;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.PKCS8EncodedKeySpec;
|
||||||
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class RSAEncryp {
|
||||||
|
|
||||||
|
public static byte[] decrypt(byte[] encryptedBytes, PrivateKey privateKey, int keyLength, int reserveSize,
|
||||||
|
String cipherAlgorithm) throws Exception {
|
||||||
|
int keyByteSize = keyLength / 8;
|
||||||
|
int decryptBlockSize = keyByteSize - reserveSize;
|
||||||
|
int nBlock = encryptedBytes.length / keyByteSize;
|
||||||
|
ByteArrayOutputStream outbuf = null;
|
||||||
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
|
||||||
|
cipher.init(Cipher.DECRYPT_MODE, privateKey);
|
||||||
|
|
||||||
|
outbuf = new ByteArrayOutputStream(nBlock * decryptBlockSize);
|
||||||
|
for (int offset = 0; offset < encryptedBytes.length; offset += keyByteSize) {
|
||||||
|
int inputLen = encryptedBytes.length - offset;
|
||||||
|
if (inputLen > keyByteSize) {
|
||||||
|
inputLen = keyByteSize;
|
||||||
|
}
|
||||||
|
byte[] decryptedBlock = cipher.doFinal(encryptedBytes, offset, inputLen);
|
||||||
|
outbuf.write(decryptedBlock);
|
||||||
|
}
|
||||||
|
outbuf.flush();
|
||||||
|
return outbuf.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Exception("DEENCRYPT ERROR:", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (outbuf != null) {
|
||||||
|
outbuf.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
outbuf = null;
|
||||||
|
throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encrypt(byte[] plainBytes, String pub_Key, int reserveSize, String cipherAlgorithm)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
PublicKey publicKey = getPublicKey(pub_Key, "RSA");
|
||||||
|
byte[] estr = encrypt(plainBytes, publicKey, pub_Key.length(), reserveSize, cipherAlgorithm);
|
||||||
|
return new String(Base64.getEncoder().encode(estr));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] encrypt(byte[] plainBytes, PublicKey publicKey, int keyLength, int reserveSize,
|
||||||
|
String cipherAlgorithm) throws Exception {
|
||||||
|
int keyByteSize = keyLength / 8;
|
||||||
|
int encryptBlockSize = keyByteSize - reserveSize;
|
||||||
|
int nBlock = plainBytes.length / encryptBlockSize;
|
||||||
|
if ((plainBytes.length % encryptBlockSize) != 0) {
|
||||||
|
nBlock += 1;
|
||||||
|
}
|
||||||
|
ByteArrayOutputStream outbuf = null;
|
||||||
|
try {
|
||||||
|
Cipher cipher = Cipher.getInstance(cipherAlgorithm);
|
||||||
|
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
|
||||||
|
|
||||||
|
outbuf = new ByteArrayOutputStream(nBlock * keyByteSize);
|
||||||
|
for (int offset = 0; offset < plainBytes.length; offset += encryptBlockSize) {
|
||||||
|
int inputLen = plainBytes.length - offset;
|
||||||
|
if (inputLen > encryptBlockSize) {
|
||||||
|
inputLen = encryptBlockSize;
|
||||||
|
}
|
||||||
|
byte[] encryptedBlock = cipher.doFinal(plainBytes, offset, inputLen);
|
||||||
|
outbuf.write(encryptedBlock);
|
||||||
|
}
|
||||||
|
outbuf.flush();
|
||||||
|
return outbuf.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Exception("ENCRYPT ERROR:", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (outbuf != null) {
|
||||||
|
outbuf.close();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
outbuf = null;
|
||||||
|
throw new Exception("CLOSE ByteArrayOutputStream ERROR:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrivateKey getPriKey(String privateKeyPath, String keyAlgorithm) {
|
||||||
|
PrivateKey privateKey = null;
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
if (inputStream == null) {
|
||||||
|
}
|
||||||
|
inputStream = new FileInputStream(privateKeyPath);
|
||||||
|
privateKey = getPrivateKey(inputStream, keyAlgorithm);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("加载私钥出错!");
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("加载私钥,关闭流时出错!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return privateKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PublicKey getPubKey(String publicKeyPath, String keyAlgorithm) {
|
||||||
|
PublicKey publicKey = null;
|
||||||
|
InputStream inputStream = null;
|
||||||
|
try {
|
||||||
|
inputStream = new FileInputStream(publicKeyPath);
|
||||||
|
publicKey = getPublicKey(inputStream, keyAlgorithm);
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("加载公钥出错!");
|
||||||
|
} finally {
|
||||||
|
if (inputStream != null) {
|
||||||
|
try {
|
||||||
|
inputStream.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.out.println("加载公钥,关闭流时出错!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return publicKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PublicKey getPublicKey(String key, String keyAlgorithm) throws Exception {
|
||||||
|
try {
|
||||||
|
org.bouncycastle.asn1.pkcs.RSAPublicKey rsaPublicKey = org.bouncycastle.asn1.pkcs.RSAPublicKey
|
||||||
|
.getInstance(org.bouncycastle.util.encoders.Base64.decode(key));
|
||||||
|
java.security.spec.RSAPublicKeySpec publicKeySpec = new java.security.spec.RSAPublicKeySpec(
|
||||||
|
rsaPublicKey.getModulus(), rsaPublicKey.getPublicExponent());
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(publicKeySpec);
|
||||||
|
|
||||||
|
return publicKey;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Exception("READ PUBLIC KEY ERROR:", e);
|
||||||
|
} finally {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PublicKey getPublicKey(InputStream inputStream, String keyAlgorithm) throws Exception {
|
||||||
|
try {
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String readLine = null;
|
||||||
|
while ((readLine = br.readLine()) != null) {
|
||||||
|
if (readLine.charAt(0) == '-') {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sb.append(readLine);
|
||||||
|
sb.append('\r');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
X509EncodedKeySpec pubX509 = new X509EncodedKeySpec(decodeBase64(sb.toString()));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
|
||||||
|
PublicKey publicKey = keyFactory.generatePublic(pubX509);
|
||||||
|
|
||||||
|
return publicKey;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Exception("READ PUBLIC KEY ERROR:", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (inputStream != null) {
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
inputStream = null;
|
||||||
|
throw new Exception("INPUT STREAM CLOSE ERROR:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static PrivateKey getPrivateKey(InputStream inputStream, String keyAlgorithm) throws Exception {
|
||||||
|
try {
|
||||||
|
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
String readLine = null;
|
||||||
|
while ((readLine = br.readLine()) != null) {
|
||||||
|
if (readLine.charAt(0) == '-') {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
sb.append(readLine);
|
||||||
|
sb.append('\r');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(decodeBase64(sb.toString()));
|
||||||
|
KeyFactory keyFactory = KeyFactory.getInstance(keyAlgorithm);
|
||||||
|
PrivateKey privateKey = keyFactory.generatePrivate(priPKCS8);
|
||||||
|
return privateKey;
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new Exception("READ PRIVATE KEY ERROR:", e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if (inputStream != null) {
|
||||||
|
inputStream.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
inputStream = null;
|
||||||
|
throw new Exception("INPUT STREAM CLOSE ERROR:", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String encodeBase64(byte[] input) throws Exception {
|
||||||
|
Class clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
|
||||||
|
Method mainMethod = clazz.getMethod("encode", byte[].class);
|
||||||
|
mainMethod.setAccessible(true);
|
||||||
|
Object retObj = mainMethod.invoke(null, new Object[] { input });
|
||||||
|
return (String) retObj;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static byte[] decodeBase64(String input) throws Exception {
|
||||||
|
Class clazz = Class.forName("com.sun.org.apache.xerces.internal.impl.dv.util.Base64");
|
||||||
|
Method mainMethod = clazz.getMethod("decode", String.class);
|
||||||
|
mainMethod.setAccessible(true);
|
||||||
|
Object retObj = mainMethod.invoke(null, input);
|
||||||
|
return (byte[]) retObj;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,175 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class SendTempleMsgBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private String appid, secret;
|
||||||
|
private static String sendUrl = "https://api.weixin.qq.com/cgi-bin/token";
|
||||||
|
private static String sendUrl2 = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";
|
||||||
|
private String access_token;
|
||||||
|
private JSONObject sendjson; // 最后发送的数据
|
||||||
|
private JSONObject data; // 自定义数据
|
||||||
|
private boolean build = false;
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param toUserOpenid
|
||||||
|
* 接收人的openid
|
||||||
|
* @param template_id
|
||||||
|
* 发送的模板ID
|
||||||
|
*/
|
||||||
|
public SendTempleMsgBuilder(String toUserOpenid, String template_id) {
|
||||||
|
// TODO Auto-generated constructor stub
|
||||||
|
sendjson = new JSONObject();
|
||||||
|
data = new JSONObject();
|
||||||
|
sendjson.put("touser", toUserOpenid);
|
||||||
|
sendjson.put("template_id", template_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppid() {
|
||||||
|
return appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppid(String appid) {
|
||||||
|
this.appid = appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSecret() {
|
||||||
|
return secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecret(String secret) {
|
||||||
|
this.secret = secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
SendTempleMsgBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAccess_token() {
|
||||||
|
return access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAccess_token(String access_token) {
|
||||||
|
this.access_token = access_token;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl2() {
|
||||||
|
return sendUrl2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl2(String sendUrl2) {
|
||||||
|
SendTempleMsgBuilder.sendUrl2 = sendUrl2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击模板消息后跳转小程序
|
||||||
|
*
|
||||||
|
* @param appid
|
||||||
|
* 跳转小程序的APPID
|
||||||
|
* @param pagepath
|
||||||
|
* 跳转的页面
|
||||||
|
*/
|
||||||
|
public void toMiniprogram(String appid, String pagepath) {
|
||||||
|
JSONObject minidata = new JSONObject();
|
||||||
|
minidata.put("appid", appid);
|
||||||
|
minidata.put("pagepath", pagepath);
|
||||||
|
sendjson.put("miniprogram", minidata);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户点击模板消息后跳转网页
|
||||||
|
*
|
||||||
|
* @param url
|
||||||
|
* 网页地址
|
||||||
|
*/
|
||||||
|
public void toUrl(String url) {
|
||||||
|
sendjson.put("url", url);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加自定义参数
|
||||||
|
*
|
||||||
|
* @param name
|
||||||
|
* 自定义参数名称
|
||||||
|
* @param color
|
||||||
|
* 十六进制颜色值
|
||||||
|
* @param value
|
||||||
|
* 具体的数据
|
||||||
|
*/
|
||||||
|
public void addCostomData(String name, String color, String value) {
|
||||||
|
JSONObject infodata = new JSONObject();
|
||||||
|
infodata.put("value", value);
|
||||||
|
infodata.put("color", color);
|
||||||
|
data.put(name, infodata);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
appendParam("appid", appid, true);
|
||||||
|
appendParam("secret", secret, true);
|
||||||
|
appendParam("grant_type", "client_credential", true);
|
||||||
|
reStringBuffer.deleteCharAt(reStringBuffer.length() - 1);
|
||||||
|
build = true;
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
JSONObject jsonObject = null;
|
||||||
|
try {
|
||||||
|
if (access_token == null) {
|
||||||
|
// 获取access_token
|
||||||
|
result = WxPayUtil.sendHttpsRequest(sendUrl, reStringBuffer.toString(), "text/xml", "utf-8", "GET");
|
||||||
|
jsonObject = JSONObject.fromObject(result);
|
||||||
|
if (jsonObject.getString("access_token") == null) {
|
||||||
|
jsonObject.put("return_code", "FAIL");
|
||||||
|
jsonObject.put("return_msg", "获取token失败");
|
||||||
|
return jsonObject;
|
||||||
|
} else {
|
||||||
|
access_token = jsonObject.getString("access_token");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = WxPayUtil.sendHttpsRequest(sendUrl2 + access_token, sendjson.toString(), "text/xml", "utf-8",
|
||||||
|
"POST");
|
||||||
|
jsonObject = JSONObject.fromObject(result);
|
||||||
|
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
// 备用域名
|
||||||
|
throw new LackParamExceptions(e.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
253
src/main/java/com/greenorange/promotion/utils/paybank/Test.java
Normal file
253
src/main/java/com/greenorange/promotion/utils/paybank/Test.java
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
public class Test {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 微信预下单 调用示例
|
||||||
|
// JSAPIPay();
|
||||||
|
// 获取openid 调用示例
|
||||||
|
// getOpenid();
|
||||||
|
// 企业付款 调用示例
|
||||||
|
// compayWxPay();
|
||||||
|
// 发送模板消息示例
|
||||||
|
// sendTempleMsg();
|
||||||
|
// 获取公钥示例
|
||||||
|
// getWxPayPublicKey();
|
||||||
|
// 付款到银行卡示例
|
||||||
|
compayWxPayBank();
|
||||||
|
// 付款到银行卡查询示例
|
||||||
|
// compayWxPayBankQuery();
|
||||||
|
// 微信退款示例
|
||||||
|
// WxPayRefund();
|
||||||
|
// 微信退款查询示例
|
||||||
|
// WxPayRefundQuery();
|
||||||
|
// 易支付示例
|
||||||
|
// EasyPayExample();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 易支付查询示例
|
||||||
|
*/
|
||||||
|
public static void EasyPayExample() {
|
||||||
|
try {
|
||||||
|
EasyPayBuilder easyPayBuilder = new EasyPayBuilder();
|
||||||
|
|
||||||
|
easyPayBuilder.setGoodsname("测试商品");
|
||||||
|
easyPayBuilder.setUid(15667);
|
||||||
|
easyPayBuilder.setIstype(1);
|
||||||
|
easyPayBuilder.setToken("5556f669bd447c9cc6cd410d0c108aa6");
|
||||||
|
easyPayBuilder.setNotify_url("");
|
||||||
|
easyPayBuilder.setReturn_url("http://www.baidu.com");
|
||||||
|
easyPayBuilder.setPrice(0.5f);
|
||||||
|
|
||||||
|
easyPayBuilder.build();// 验证数据
|
||||||
|
System.out.println(easyPayBuilder.hand());// 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信退款查询示例
|
||||||
|
*/
|
||||||
|
public static void WxPayRefundQuery() {
|
||||||
|
try {
|
||||||
|
WxPayRefundQueryBuilder wxPayRefundBuilder = new WxPayRefundQueryBuilder();
|
||||||
|
wxPayRefundBuilder.setAppid("小程序或公众号APPID");
|
||||||
|
wxPayRefundBuilder.setMch_id("商户号");
|
||||||
|
wxPayRefundBuilder.setAPI_KEY("商户号APIKEY");
|
||||||
|
// 下面四个任选一个
|
||||||
|
wxPayRefundBuilder.setOut_trade_no("商家交易订单号");
|
||||||
|
wxPayRefundBuilder.setOut_refund_no("退款商家订单号");
|
||||||
|
wxPayRefundBuilder.setTransaction_id("微信交易订单号");
|
||||||
|
wxPayRefundBuilder.setRefund_id("退款微信订单号");
|
||||||
|
|
||||||
|
wxPayRefundBuilder.build();// 验证数据
|
||||||
|
System.out.println(wxPayRefundBuilder.hand());// 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信退款示例
|
||||||
|
*/
|
||||||
|
public static void WxPayRefund() {
|
||||||
|
try {
|
||||||
|
WxPayRefundBuilder wxPayRefundBuilder = new WxPayRefundBuilder("证书路径");
|
||||||
|
wxPayRefundBuilder.setAppid("小程序或公众号APPID");
|
||||||
|
wxPayRefundBuilder.setMch_id("商户号");
|
||||||
|
wxPayRefundBuilder.setAPI_KEY("商户号APIKEY");
|
||||||
|
wxPayRefundBuilder.setTotal_fee(101);// 该订单总金额
|
||||||
|
wxPayRefundBuilder.setRefund_fee(101); // 退款金额
|
||||||
|
wxPayRefundBuilder.setRefund_desc("测试"); // 退款描述
|
||||||
|
// 任选一个
|
||||||
|
wxPayRefundBuilder.setOut_trade_no("商家交易订单号");
|
||||||
|
wxPayRefundBuilder.setTransaction_id("微信交易订单号");
|
||||||
|
|
||||||
|
wxPayRefundBuilder.build();// 验证数据
|
||||||
|
System.out.println(wxPayRefundBuilder.hand());// 发送处理
|
||||||
|
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业付款到银行卡查询示例
|
||||||
|
*/
|
||||||
|
public static void compayWxPayBankQuery() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
CompanyWxPayBankQueryBuilder wxPayBankQueryBuilder = new CompanyWxPayBankQueryBuilder("支付证书路径",
|
||||||
|
"交易订单号(商家,不是微信的)");
|
||||||
|
|
||||||
|
wxPayBankQueryBuilder.setMch_id("商户号");
|
||||||
|
wxPayBankQueryBuilder.setAPI_KEY("APIKEY");
|
||||||
|
|
||||||
|
wxPayBankQueryBuilder.build();// 验证数据
|
||||||
|
System.out.println(wxPayBankQueryBuilder.hand());// 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业付款到银行卡示例
|
||||||
|
*/
|
||||||
|
public static void compayWxPayBank() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取公钥
|
||||||
|
String key = getWxPayPublicKey();
|
||||||
|
|
||||||
|
CompanyWxPayBankBuilder wxPayBankBuilder = new CompanyWxPayBankBuilder("src/main/resources/static/apiclient_cert.p12", key); // key 为微信返回的公钥
|
||||||
|
|
||||||
|
wxPayBankBuilder.setMch_id("1700326544");
|
||||||
|
wxPayBankBuilder.setAPI_KEY("cvsOH6TgbbdNUUqFJyLmWGaIEKoSqANg");
|
||||||
|
wxPayBankBuilder.setAmount(2); // 支付金额
|
||||||
|
wxPayBankBuilder.setDesc("提现");
|
||||||
|
wxPayBankBuilder.setEnc_bank_no("6222031207006363442");
|
||||||
|
wxPayBankBuilder.setEnc_true_name("陈新知");
|
||||||
|
wxPayBankBuilder.setBank_code("1002");
|
||||||
|
|
||||||
|
wxPayBankBuilder.build();// 验证数据
|
||||||
|
System.out.println(wxPayBankBuilder.hand());// 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取公钥
|
||||||
|
*/
|
||||||
|
public static String getWxPayPublicKey() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
GetPublicKeyBuilder builder = new GetPublicKeyBuilder("src/main/resources/static/apiclient_cert.p12");
|
||||||
|
builder.setAPI_KEY("cvsOH6TgbbdNUUqFJyLmWGaIEKoSqANg");
|
||||||
|
builder.setmch_id("1700326544");
|
||||||
|
|
||||||
|
builder.build();// 验证数据
|
||||||
|
JSONObject result = builder.hand();
|
||||||
|
System.out.println(result);// 发送处理
|
||||||
|
return result.getString("pub_key");
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 微信预下单 调用示例
|
||||||
|
*/
|
||||||
|
public static void JSAPIPay() {
|
||||||
|
try {
|
||||||
|
JSAPIWxPayBuilder jsapiWxPayBuilder = new JSAPIWxPayBuilder();
|
||||||
|
jsapiWxPayBuilder.setAppid("小程序APPID");
|
||||||
|
jsapiWxPayBuilder.setAttach("携带参数");
|
||||||
|
jsapiWxPayBuilder.setMch_id("商户号");
|
||||||
|
jsapiWxPayBuilder.setAPI_KEY("商户号API秘钥");
|
||||||
|
jsapiWxPayBuilder.setBody("商品内容");
|
||||||
|
jsapiWxPayBuilder.setTotal_fee(50); // 交易金额
|
||||||
|
jsapiWxPayBuilder.setNotify_url("回调地址"); //
|
||||||
|
jsapiWxPayBuilder.setSpbill_create_ip("发起请求的IP"); //
|
||||||
|
jsapiWxPayBuilder.setOpenid("OPENID");
|
||||||
|
|
||||||
|
jsapiWxPayBuilder.build();// 验证数据
|
||||||
|
System.out.println(jsapiWxPayBuilder.hand());// 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取openid 调用示例
|
||||||
|
*/
|
||||||
|
public static void getOpenid() {
|
||||||
|
try {
|
||||||
|
GetOpenidBuilder getOpenidBuilder = new GetOpenidBuilder();
|
||||||
|
getOpenidBuilder.setAppid("您的小程序Openid");
|
||||||
|
getOpenidBuilder.setAppsecret("您的小程序秘钥");
|
||||||
|
getOpenidBuilder.setCode("小程序登陆时获取的code");
|
||||||
|
getOpenidBuilder.build();// 验证数据
|
||||||
|
System.out.println(getOpenidBuilder.hand());// 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 企业付款 调用示例
|
||||||
|
*/
|
||||||
|
public static void compayWxPay() {
|
||||||
|
try {
|
||||||
|
|
||||||
|
CompanyWxPayBuilder compayBuilder = new CompanyWxPayBuilder(
|
||||||
|
"C:\\Users\\Administrator\\Desktop\\远程\\apiclient_cert.p12");
|
||||||
|
compayBuilder.setMch_appid("被付款人使用的小程序appid或公众号appid");
|
||||||
|
compayBuilder.setAPI_KEY("您的商户号API操作秘钥");
|
||||||
|
compayBuilder.setDesc("付款备注");
|
||||||
|
compayBuilder.setMchid("您的商户号");
|
||||||
|
compayBuilder.setOpenid("小程序或公众号对应的openid");
|
||||||
|
compayBuilder.setSpbill_create_ip("本机ip,不能是 localhost或127.0.0.1");
|
||||||
|
compayBuilder.setAmount(200); // 支付金额
|
||||||
|
|
||||||
|
// compayBuilder.setMch_appid("wxafa0aa182e6570ca");
|
||||||
|
// compayBuilder.setAPI_KEY("MvK6aVg00EUxzOyWDOHUWvMTk2PQtdZi");
|
||||||
|
// compayBuilder.setDesc("提现");
|
||||||
|
// compayBuilder.setMchid("1343097401");
|
||||||
|
// compayBuilder.setOpenid("o90eTt95OlE-u8mblsklZNfxpPuw");
|
||||||
|
// compayBuilder.setSpbill_create_ip("182.92.119.83");
|
||||||
|
// compayBuilder.setAmount(100); // 支付金额
|
||||||
|
|
||||||
|
compayBuilder.build(); // 验证数据
|
||||||
|
System.out.println(compayBuilder.hand()); // 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 发送模板消息示例
|
||||||
|
*/
|
||||||
|
public static void sendTempleMsg() {
|
||||||
|
try {
|
||||||
|
SendTempleMsgBuilder sendTempleMsgBuilder = new SendTempleMsgBuilder("公众号APPID", "发送模板ID");
|
||||||
|
sendTempleMsgBuilder.setAccess_token("access——token");
|
||||||
|
sendTempleMsgBuilder.toMiniprogram("用户点击模板消息时跳转小程序的APPID", "跳转路径");
|
||||||
|
sendTempleMsgBuilder.toUrl("用户点击模板消息时跳转的网址");
|
||||||
|
sendTempleMsgBuilder.addCostomData("自定义数据名称", "十六进制颜色值", "具体数值"); // 添加自定义数据
|
||||||
|
// 示例
|
||||||
|
sendTempleMsgBuilder.addCostomData("first", "#ff0000", "您有新的故障通知");
|
||||||
|
sendTempleMsgBuilder.build(); // 验证数据
|
||||||
|
System.out.println(sendTempleMsgBuilder.hand()); // 发送处理
|
||||||
|
} catch (LackParamExceptions e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,68 @@
|
||||||
|
package com.mx.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
public class WeChatAPIV3Manager {
|
||||||
|
static volatile WeChatAPIV3Manager weChatAPIV3Manager = null;
|
||||||
|
|
||||||
|
ConcurrentHashMap<String,WeChatAPIV3> weChatAPIV3Map = null;
|
||||||
|
|
||||||
|
long lastClearTime = 0l;
|
||||||
|
|
||||||
|
private WeChatAPIV3Manager(){
|
||||||
|
weChatAPIV3Map = new ConcurrentHashMap<>();
|
||||||
|
lastClearTime = System.currentTimeMillis() / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeChatAPIV3 getWeChatApiV3(String mchid){
|
||||||
|
long lCurTime = System.currentTimeMillis() / 1000;
|
||||||
|
WeChatAPIV3 weChatAPIV3 = weChatAPIV3Map.get(mchid);
|
||||||
|
if(weChatAPIV3 != null && lCurTime - weChatAPIV3.getLastUseTime() > 3 * 3600){
|
||||||
|
weChatAPIV3Map.remove(mchid);
|
||||||
|
weChatAPIV3 = null;
|
||||||
|
}
|
||||||
|
if(weChatAPIV3 != null){
|
||||||
|
weChatAPIV3.setLastUseTime(lCurTime);
|
||||||
|
}
|
||||||
|
clearNoUserObject();
|
||||||
|
return weChatAPIV3;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWeChatAPIV3Map(String mchid,WeChatAPIV3 weChatAPIV3){
|
||||||
|
if(weChatAPIV3 != null && weChatAPIV3.isStep()){
|
||||||
|
weChatAPIV3.setLastUseTime(System.currentTimeMillis() / 1000);
|
||||||
|
weChatAPIV3Map.put(mchid,weChatAPIV3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public WeChatAPIV3 remove(String mchid){
|
||||||
|
return weChatAPIV3Map.remove(mchid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void clearNoUserObject(){
|
||||||
|
long lCurTime = System.currentTimeMillis() / 1000;
|
||||||
|
if(weChatAPIV3Map == null || lCurTime - lastClearTime >= 3 * 3600){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Set<Map.Entry<String, WeChatAPIV3>> entries = weChatAPIV3Map.entrySet();
|
||||||
|
for(Map.Entry<String, WeChatAPIV3> entrie:entries){
|
||||||
|
if(lCurTime - entrie.getValue().getLastUseTime() >= 3 * 3600){
|
||||||
|
weChatAPIV3Map.remove(entrie.getKey());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastClearTime = lCurTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static WeChatAPIV3Manager getInstance(){
|
||||||
|
if (weChatAPIV3Manager == null){
|
||||||
|
synchronized (WeChatAPIV3Manager.class){
|
||||||
|
if (weChatAPIV3Manager == null){
|
||||||
|
weChatAPIV3Manager = new WeChatAPIV3Manager();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return weChatAPIV3Manager;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
interface WxPayDataBuilder {
|
||||||
|
boolean build() throws LackParamExceptions;
|
||||||
|
|
||||||
|
JSONObject hand() throws LackParamExceptions;
|
||||||
|
}
|
|
@ -0,0 +1,271 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class WxPayRefundBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private static String sendUrl = "https://api.mch.weixin.qq.com/secapi/pay/refund";
|
||||||
|
|
||||||
|
private String appid, mch_id, transaction_id, out_refund_no, out_trade_no, refund_fee_type, refund_desc, sign,
|
||||||
|
API_KEY, nonce_str, notify_url, certPath, refund_account;
|
||||||
|
|
||||||
|
private int total_fee, refund_fee;
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public WxPayRefundBuilder(String certPath) {
|
||||||
|
nonce_str = WxPayUtil.getRandomStr(20);
|
||||||
|
this.certPath = certPath;
|
||||||
|
// 默认订单时间为半小时内有效
|
||||||
|
out_refund_no = System.currentTimeMillis() + WxPayUtil.getRandomStr(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotify_url() {
|
||||||
|
return notify_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotify_url(String notify_url) {
|
||||||
|
this.notify_url = notify_url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCertPath() {
|
||||||
|
return certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCertPath(String certPath) {
|
||||||
|
this.certPath = certPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRefund_account() {
|
||||||
|
return refund_account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRefund_account(String refund_account) {
|
||||||
|
this.refund_account = refund_account;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
WxPayRefundBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppid() {
|
||||||
|
return appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppid(String appid) {
|
||||||
|
this.appid = appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTransaction_id() {
|
||||||
|
return transaction_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransaction_id(String transaction_id) {
|
||||||
|
this.transaction_id = transaction_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOut_refund_no() {
|
||||||
|
return out_refund_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOut_refund_no(String out_refund_no) {
|
||||||
|
this.out_refund_no = out_refund_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOut_trade_no() {
|
||||||
|
return out_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOut_trade_no(String out_trade_no) {
|
||||||
|
this.out_trade_no = out_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRefund_fee_type() {
|
||||||
|
return refund_fee_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRefund_fee_type(String refund_fee_type) {
|
||||||
|
this.refund_fee_type = refund_fee_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRefund_desc() {
|
||||||
|
return refund_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRefund_desc(String refund_desc) {
|
||||||
|
this.refund_desc = refund_desc;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSign() {
|
||||||
|
return sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSign(String sign) {
|
||||||
|
this.sign = sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAPI_KEY() {
|
||||||
|
return API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAPI_KEY(String aPI_KEY) {
|
||||||
|
API_KEY = aPI_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNonce_str() {
|
||||||
|
return nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonce_str(String nonce_str) {
|
||||||
|
this.nonce_str = nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getTotal_fee() {
|
||||||
|
return total_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTotal_fee(int total_fee) {
|
||||||
|
this.total_fee = total_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuffer getReStringBuffer() {
|
||||||
|
return reStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReStringBuffer(StringBuffer reStringBuffer) {
|
||||||
|
this.reStringBuffer = reStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuffer getSignStringBuffer() {
|
||||||
|
return signStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignStringBuffer(StringBuffer signStringBuffer) {
|
||||||
|
this.signStringBuffer = signStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBuild() {
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBuild(boolean build) {
|
||||||
|
this.build = build;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRefund_fee() {
|
||||||
|
return refund_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRefund_fee(int refund_fee) {
|
||||||
|
this.refund_fee = refund_fee;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
reStringBuffer.append("<xml>");
|
||||||
|
appendParam("appid", appid, true);
|
||||||
|
appendParam("mch_id", mch_id, true);
|
||||||
|
appendParam("nonce_str", nonce_str, true);
|
||||||
|
appendParam("notify_url", notify_url, false);
|
||||||
|
appendParam("out_refund_no", out_refund_no, true);
|
||||||
|
appendParam("out_trade_no", out_trade_no, false);
|
||||||
|
appendParam("refund_account", refund_account, false);
|
||||||
|
appendParam("refund_desc", refund_desc, false);
|
||||||
|
appendParam("refund_fee", refund_fee + "", true);
|
||||||
|
appendParam("refund_fee_type", refund_fee_type, false);
|
||||||
|
appendParam("sign_type", "MD5", false);
|
||||||
|
appendParam("total_fee", total_fee + "", true);
|
||||||
|
appendParam("transaction_id", transaction_id, false);
|
||||||
|
getSign(API_KEY, this.signStringBuffer.toString());
|
||||||
|
appendParam("sign", sign.toUpperCase(), true);
|
||||||
|
|
||||||
|
reStringBuffer.append("</xml>");
|
||||||
|
|
||||||
|
build = true;
|
||||||
|
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSign(String apikey, String value) throws LackParamExceptions {
|
||||||
|
if (apikey == null) {
|
||||||
|
throw new LackParamExceptions("商户号操作秘钥不能为空");
|
||||||
|
} else {
|
||||||
|
sign = WxPayUtil.MD5(value + "key=" + API_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append("<" + key + ">");
|
||||||
|
this.reStringBuffer.append("<![CDATA[" + value + "]]>");
|
||||||
|
this.reStringBuffer.append("</" + key + ">");
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
JSONObject resultJson = new JSONObject();
|
||||||
|
try {
|
||||||
|
result = WxPayUtil.doPostDataWithCert(sendUrl, reStringBuffer.toString(), mch_id, certPath);
|
||||||
|
|
||||||
|
Map<String, String> getResult = WxPayUtil.xmlToMap(result);
|
||||||
|
|
||||||
|
if (getResult.get("result_code") == null || !"SUCCESS".equalsIgnoreCase(getResult.get("result_code"))) {
|
||||||
|
resultJson.put("return_code", "FAIL");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
} else {
|
||||||
|
resultJson.put("return_code", "SUCCESS");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("out_refund_no", getResult.get("out_refund_no"));
|
||||||
|
resultJson.put("out_trade_no", getResult.get("out_trade_no"));
|
||||||
|
resultJson.put("refund_fee", getResult.get("refund_fee"));
|
||||||
|
resultJson.put("refund_id", getResult.get("refund_id"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// TODO Auto-generated catch block
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,211 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class WxPayRefundQueryBuilder implements WxPayDataBuilder {
|
||||||
|
|
||||||
|
private static String sendUrl = "https://api.mch.weixin.qq.com/pay/refundquery";
|
||||||
|
|
||||||
|
private String appid, mch_id, transaction_id, out_refund_no, out_trade_no, refund_id, sign, API_KEY, nonce_str;
|
||||||
|
|
||||||
|
private StringBuffer reStringBuffer;
|
||||||
|
private StringBuffer signStringBuffer;
|
||||||
|
private boolean build = false;
|
||||||
|
|
||||||
|
public WxPayRefundQueryBuilder() {
|
||||||
|
nonce_str = WxPayUtil.getRandomStr(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuffer getReStringBuffer() {
|
||||||
|
return reStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReStringBuffer(StringBuffer reStringBuffer) {
|
||||||
|
this.reStringBuffer = reStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuffer getSignStringBuffer() {
|
||||||
|
return signStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignStringBuffer(StringBuffer signStringBuffer) {
|
||||||
|
this.signStringBuffer = signStringBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getSendUrl() {
|
||||||
|
return sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setSendUrl(String sendUrl) {
|
||||||
|
WxPayRefundQueryBuilder.sendUrl = sendUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAppid() {
|
||||||
|
return appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAppid(String appid) {
|
||||||
|
this.appid = appid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMch_id() {
|
||||||
|
return mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMch_id(String mch_id) {
|
||||||
|
this.mch_id = mch_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTransaction_id() {
|
||||||
|
return transaction_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTransaction_id(String transaction_id) {
|
||||||
|
this.transaction_id = transaction_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOut_refund_no() {
|
||||||
|
return out_refund_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOut_refund_no(String out_refund_no) {
|
||||||
|
this.out_refund_no = out_refund_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOut_trade_no() {
|
||||||
|
return out_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOut_trade_no(String out_trade_no) {
|
||||||
|
this.out_trade_no = out_trade_no;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRefund_id() {
|
||||||
|
return refund_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRefund_id(String refund_id) {
|
||||||
|
this.refund_id = refund_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSign() {
|
||||||
|
return sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSign(String sign) {
|
||||||
|
this.sign = sign;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAPI_KEY() {
|
||||||
|
return API_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAPI_KEY(String aPI_KEY) {
|
||||||
|
API_KEY = aPI_KEY;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNonce_str() {
|
||||||
|
return nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNonce_str(String nonce_str) {
|
||||||
|
this.nonce_str = nonce_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isBuild() {
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBuild(boolean build) {
|
||||||
|
this.build = build;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean build() throws LackParamExceptions {
|
||||||
|
build = false;
|
||||||
|
reStringBuffer = new StringBuffer();
|
||||||
|
signStringBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
reStringBuffer.append("<xml>");
|
||||||
|
appendParam("appid", appid, true);
|
||||||
|
appendParam("mch_id", mch_id, true);
|
||||||
|
appendParam("nonce_str", nonce_str, true);
|
||||||
|
appendParam("out_refund_no", out_refund_no, false);
|
||||||
|
appendParam("out_trade_no", out_trade_no, false);
|
||||||
|
appendParam("refund_id", refund_id, false);
|
||||||
|
appendParam("sign_type", "MD5", false);
|
||||||
|
appendParam("transaction_id", transaction_id, false);
|
||||||
|
getSign(API_KEY, this.signStringBuffer.toString());
|
||||||
|
appendParam("sign", sign.toUpperCase(), true);
|
||||||
|
|
||||||
|
reStringBuffer.append("</xml>");
|
||||||
|
|
||||||
|
build = true;
|
||||||
|
|
||||||
|
return build;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getSign(String apikey, String value) throws LackParamExceptions {
|
||||||
|
if (apikey == null) {
|
||||||
|
throw new LackParamExceptions("商户号操作秘钥不能为空");
|
||||||
|
} else {
|
||||||
|
sign = WxPayUtil.MD5(value + "key=" + API_KEY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void appendParam(String key, String value, boolean isneed) throws LackParamExceptions {
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
if (isneed) {
|
||||||
|
throw new LackParamExceptions("参数" + key + "不能为空");
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.reStringBuffer.append("<" + key + ">");
|
||||||
|
this.reStringBuffer.append("<![CDATA[" + value + "]]>");
|
||||||
|
this.reStringBuffer.append("</" + key + ">");
|
||||||
|
this.signStringBuffer.append(key + "=" + value + "&");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JSONObject hand() throws LackParamExceptions {
|
||||||
|
if (!build) {
|
||||||
|
throw new LackParamExceptions("未build成功,请先确认build成功后再运行");
|
||||||
|
}
|
||||||
|
String result = "";
|
||||||
|
JSONObject resultJson = new JSONObject();
|
||||||
|
try {
|
||||||
|
result = WxPayUtil.sendHttpsRequest(sendUrl, reStringBuffer.toString(), "text/xml", "utf-8", "POST");
|
||||||
|
|
||||||
|
Map<String, String> getResult = WxPayUtil.xmlToMap(result);
|
||||||
|
|
||||||
|
if (getResult.get("result_code") == null || !"SUCCESS".equalsIgnoreCase(getResult.get("result_code"))) {
|
||||||
|
resultJson.put("return_code", "FAIL");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
} else {
|
||||||
|
resultJson.put("return_code", "SUCCESS");
|
||||||
|
resultJson.put("return_msg", getResult.get("return_msg"));
|
||||||
|
resultJson.put("err_code", getResult.get("err_code"));
|
||||||
|
resultJson.put("err_code_des", getResult.get("err_code_des"));
|
||||||
|
resultJson.put("out_refund_no", getResult.get("out_refund_no"));
|
||||||
|
resultJson.put("refund_count", getResult.get("refund_count"));
|
||||||
|
resultJson.put("transaction_id", getResult.get("transaction_id"));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultJson;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,389 @@
|
||||||
|
package com.greenorange.promotion.utils.paybank;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.io.OutputStreamWriter;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.security.KeyStore;
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
import javax.net.ssl.SSLContext;
|
||||||
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
|
|
||||||
|
|
||||||
|
import net.sf.json.JSONObject;
|
||||||
|
import net.sf.json.xml.XMLSerializer;
|
||||||
|
import org.apache.http.HttpEntity;
|
||||||
|
import org.apache.http.client.ClientProtocolException;
|
||||||
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
import org.apache.http.client.methods.HttpPost;
|
||||||
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
|
import org.apache.http.conn.ssl.SSLContexts;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
import org.apache.http.util.EntityUtils;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* v1.0.2
|
||||||
|
*
|
||||||
|
* @author 周工 2020-06-01
|
||||||
|
*/
|
||||||
|
public class WxPayUtil {
|
||||||
|
private static SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||||
|
|
||||||
|
public static String getRandomStr(int length) {
|
||||||
|
String chars = "abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||||
|
+ System.currentTimeMillis();/**/
|
||||||
|
int maxPos = chars.length();
|
||||||
|
String[] charsMore = chars.split("");
|
||||||
|
StringBuffer noceStr = new StringBuffer();
|
||||||
|
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
noceStr.append(charsMore[(int) Math.floor(Math.random() * maxPos)]);
|
||||||
|
}
|
||||||
|
return noceStr.toString(); // 随机数
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String MD5(String str) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
|
||||||
|
byte[] bytes = messageDigest.digest(str.getBytes("utf-8"));
|
||||||
|
return byteArrayToHexString(bytes);
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String hexDigits[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d",
|
||||||
|
"e", "f" };
|
||||||
|
|
||||||
|
private static String byteToHexString(byte b) {
|
||||||
|
|
||||||
|
int n = b;
|
||||||
|
if (n < 0) {
|
||||||
|
n += 256;
|
||||||
|
}
|
||||||
|
int d1 = n / 16;
|
||||||
|
int d2 = n % 16;
|
||||||
|
return hexDigits[d1] + hexDigits[d2];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map<String, String> xmlToMap(String xml) {
|
||||||
|
try {
|
||||||
|
Map<String, String> data = new HashMap<>();
|
||||||
|
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
|
||||||
|
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
|
||||||
|
InputStream stream = new ByteArrayInputStream(xml.getBytes("UTF-8"));
|
||||||
|
org.w3c.dom.Document doc = documentBuilder.parse(stream);
|
||||||
|
doc.getDocumentElement().normalize();
|
||||||
|
NodeList nodeList = doc.getDocumentElement().getChildNodes();
|
||||||
|
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
|
||||||
|
Node node = nodeList.item(idx);
|
||||||
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
|
||||||
|
data.put(element.getNodeName(), element.getTextContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
stream.close();
|
||||||
|
return data;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String byteArrayToHexString(byte[] digest) {
|
||||||
|
StringBuffer result = new StringBuffer();
|
||||||
|
for (byte b : digest) {
|
||||||
|
result.append(byteToHexString(b));
|
||||||
|
}
|
||||||
|
return result.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String FormatDate(long timeinmill) {
|
||||||
|
return sDateFormat.format(new Date(timeinmill));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static JSONObject XmlParseJSON(String xml) {
|
||||||
|
XMLSerializer xmlSerializer = new XMLSerializer();
|
||||||
|
String resutStr = xmlSerializer.read(xml).toString();
|
||||||
|
JSONObject result = JSONObject.fromObject(resutStr);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sendHttpsRequest(String url, String data, String sendType, String contentType, String methed)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
if ("GET".equals(methed)) {
|
||||||
|
url = url.indexOf("?") >= 0 ? url + data : url + "?" + data;
|
||||||
|
}
|
||||||
|
if (sendType == null) {
|
||||||
|
sendType = "text/xml";
|
||||||
|
}
|
||||||
|
if (contentType == null) {
|
||||||
|
contentType = "utf-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
URL requestUrl = new URL(url);
|
||||||
|
HttpsURLConnection connection = (HttpsURLConnection) requestUrl.openConnection();
|
||||||
|
connection.setDoInput(true); // 允许输入流,即允许下<EFBFBD>?
|
||||||
|
connection.setDoOutput(true); // 允许输出流,即允许上<EFBFBD>?
|
||||||
|
connection.setUseCaches(false); // 不使用缓<EFBFBD>?
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
|
||||||
|
|
||||||
|
if ("POST".equals(methed)) {
|
||||||
|
connection.setRequestProperty("Content-type", sendType);
|
||||||
|
connection.setRequestProperty("Cache-Control", "no-cache");
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
|
||||||
|
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
|
||||||
|
|
||||||
|
out.write(new String(data.getBytes(contentType)));
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} else {
|
||||||
|
connection.setRequestMethod("GET"); // 使用get请求
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = connection.getInputStream(); // 获取输入流,此时才真正建立链<EFBFBD>?
|
||||||
|
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
InputStreamReader isr = new InputStreamReader(is, "utf-8");
|
||||||
|
BufferedReader bufferReader = new BufferedReader(isr);
|
||||||
|
String inputLine = "";
|
||||||
|
|
||||||
|
while ((inputLine = bufferReader.readLine()) != null) {
|
||||||
|
stringBuffer.append(inputLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
is.close();
|
||||||
|
connection.disconnect();
|
||||||
|
return stringBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sendHttpsRequest(String url, String data, String sendType, String contentType, String methed,
|
||||||
|
String Authorization) throws IOException {
|
||||||
|
|
||||||
|
if ("GET".equals(methed)) {
|
||||||
|
url = url.indexOf("?") >= 0 ? url + data : url + "?" + data;
|
||||||
|
}
|
||||||
|
if (sendType == null) {
|
||||||
|
sendType = "text/xml";
|
||||||
|
}
|
||||||
|
if (contentType == null) {
|
||||||
|
contentType = "utf-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
URL requestUrl = new URL(url);
|
||||||
|
HttpsURLConnection connection = (HttpsURLConnection) requestUrl.openConnection();
|
||||||
|
connection.setDoInput(true); // 允许输入流,即允许下<EFBFBD>?
|
||||||
|
connection.setDoOutput(true); // 允许输出流,即允许上<EFBFBD>?
|
||||||
|
connection.setUseCaches(false); // 不使用缓<EFBFBD>?
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
|
||||||
|
connection.addRequestProperty("Authorization", Authorization);
|
||||||
|
|
||||||
|
if ("POST".equals(methed)) {
|
||||||
|
// connection.setRequestProperty("Content-type", sendType);
|
||||||
|
connection.setRequestProperty("Cache-Control", "no-cache");
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
|
||||||
|
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
|
||||||
|
|
||||||
|
out.write(new String(data.getBytes(contentType)));
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} else {
|
||||||
|
connection.setRequestMethod("GET"); // 使用get请求
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = connection.getInputStream(); // 获取输入流,此时才真正建立链<EFBFBD>?
|
||||||
|
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
InputStreamReader isr = new InputStreamReader(is, "utf-8");
|
||||||
|
BufferedReader bufferReader = new BufferedReader(isr);
|
||||||
|
String inputLine = "";
|
||||||
|
|
||||||
|
while ((inputLine = bufferReader.readLine()) != null) {
|
||||||
|
stringBuffer.append(inputLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
is.close();
|
||||||
|
connection.disconnect();
|
||||||
|
return stringBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String sendHttpRequest(String url, String data, String sendType, String contentType, String methed)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
if ("GET".equals(methed)) {
|
||||||
|
url = url.indexOf("?") >= 0 ? url + data : url + "?" + data;
|
||||||
|
}
|
||||||
|
if (sendType == null) {
|
||||||
|
sendType = "text/xml";
|
||||||
|
}
|
||||||
|
if (contentType == null) {
|
||||||
|
contentType = "utf-8";
|
||||||
|
}
|
||||||
|
|
||||||
|
URL requestUrl = new URL(url);
|
||||||
|
HttpURLConnection connection = (HttpURLConnection) requestUrl.openConnection();
|
||||||
|
connection.setDoInput(true); // 允许输入流,即允许下<EFBFBD>?
|
||||||
|
connection.setDoOutput(true); // 允许输出流,即允许上<EFBFBD>?
|
||||||
|
connection.setUseCaches(false); // 不使用缓<EFBFBD>?
|
||||||
|
connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
|
||||||
|
|
||||||
|
if ("POST".equals(methed)) {
|
||||||
|
connection.setRequestProperty("Content-type", sendType);
|
||||||
|
connection.setRequestProperty("Cache-Control", "no-cache");
|
||||||
|
connection.setRequestMethod("POST");
|
||||||
|
|
||||||
|
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
|
||||||
|
|
||||||
|
out.write(new String(data.getBytes(contentType)));
|
||||||
|
out.flush();
|
||||||
|
out.close();
|
||||||
|
} else {
|
||||||
|
connection.setRequestMethod("GET"); // 使用get请求
|
||||||
|
}
|
||||||
|
|
||||||
|
InputStream is = connection.getInputStream(); // 获取输入流,此时才真正建立链<EFBFBD>?
|
||||||
|
|
||||||
|
StringBuffer stringBuffer = new StringBuffer();
|
||||||
|
InputStreamReader isr = new InputStreamReader(is, "utf-8");
|
||||||
|
BufferedReader bufferReader = new BufferedReader(isr);
|
||||||
|
String inputLine = "";
|
||||||
|
|
||||||
|
while ((inputLine = bufferReader.readLine()) != null) {
|
||||||
|
stringBuffer.append(inputLine);
|
||||||
|
}
|
||||||
|
|
||||||
|
is.close();
|
||||||
|
connection.disconnect();
|
||||||
|
return stringBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String httpClientResultGetPublicKey(String url, String xml, String mch_id, String path)
|
||||||
|
throws Exception {
|
||||||
|
|
||||||
|
StringBuffer reultBuffer = new StringBuffer();
|
||||||
|
|
||||||
|
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||||
|
|
||||||
|
FileInputStream instream = new FileInputStream(new File(path));
|
||||||
|
try {
|
||||||
|
|
||||||
|
keyStore.load(instream, mch_id.toCharArray());
|
||||||
|
} finally {
|
||||||
|
instream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray()).build();
|
||||||
|
|
||||||
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1", "TLSv1.2" }, null,
|
||||||
|
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
|
||||||
|
|
||||||
|
HttpPost httpPost = new HttpPost(url);
|
||||||
|
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||||
|
StringEntity myEntity = new StringEntity(xml);
|
||||||
|
myEntity.setContentType("text/xml;charset=UTF-8");
|
||||||
|
myEntity.setContentEncoding("utf-8");
|
||||||
|
httpPost.setHeader("Content-Type", "text/xml; charset=UTF-8");
|
||||||
|
httpPost.setEntity(myEntity);
|
||||||
|
|
||||||
|
CloseableHttpResponse response = null;
|
||||||
|
InputStream inputStream = null;
|
||||||
|
InputStreamReader inputStreamReader = null;
|
||||||
|
BufferedReader bufferedReader = null;
|
||||||
|
try {
|
||||||
|
response = httpclient.execute(httpPost);
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
if (entity != null) {
|
||||||
|
inputStream = entity.getContent();
|
||||||
|
inputStreamReader = new InputStreamReader(inputStream);
|
||||||
|
bufferedReader = new BufferedReader(inputStreamReader);
|
||||||
|
String str = null;
|
||||||
|
while ((str = bufferedReader.readLine()) != null) {
|
||||||
|
reultBuffer.append(str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (ClientProtocolException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} finally {
|
||||||
|
|
||||||
|
httpclient.close();
|
||||||
|
response.close();
|
||||||
|
bufferedReader.close();
|
||||||
|
inputStreamReader.close();
|
||||||
|
inputStream.close();
|
||||||
|
inputStream = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reultBuffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String doPostDataWithCert(String url, String data, String mch_id, String filPath) throws Exception {
|
||||||
|
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||||
|
FileInputStream instream = new FileInputStream(new File(filPath));// P12文件目录
|
||||||
|
|
||||||
|
try {
|
||||||
|
keyStore.load(instream, mch_id.toCharArray());
|
||||||
|
} finally {
|
||||||
|
instream.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
SSLContext sslcontext = SSLContexts.custom().loadKeyMaterial(keyStore, mch_id.toCharArray())// 这里也是写密码的
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslcontext, new String[] { "TLSv1", "TLSv1.2" }, null,
|
||||||
|
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
|
||||||
|
|
||||||
|
CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build();
|
||||||
|
|
||||||
|
try {
|
||||||
|
HttpPost httpost = new HttpPost(url); // 设置响应头信息
|
||||||
|
httpost.addHeader("Connection", "keep-alive");
|
||||||
|
httpost.addHeader("Accept", "*/*");
|
||||||
|
httpost.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
|
||||||
|
httpost.addHeader("Host", "api.mch.weixin.qq.com");
|
||||||
|
httpost.addHeader("X-Requested-With", "XMLHttpRequest");
|
||||||
|
httpost.addHeader("Cache-Control", "max-age=0");
|
||||||
|
httpost.addHeader("User-Agent", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0) ");
|
||||||
|
httpost.setEntity(new StringEntity(data, "UTF-8"));
|
||||||
|
CloseableHttpResponse response = httpclient.execute(httpost);
|
||||||
|
try {
|
||||||
|
HttpEntity entity = response.getEntity();
|
||||||
|
|
||||||
|
String jsonStr = EntityUtils.toString(response.getEntity(), "UTF-8");
|
||||||
|
EntityUtils.consume(entity);
|
||||||
|
return jsonStr;
|
||||||
|
} finally {
|
||||||
|
response.close();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
httpclient.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -1,8 +1,5 @@
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||||
url: jdbc:mysql://8.130.119.119:3306/qingcheng?serverTimezone=Asia/Shanghai
|
url: jdbc:mysql://8.130.119.119:3306/qingcheng?serverTimezone=Asia/Shanghai
|
||||||
username: qingcheng
|
username: qingcheng
|
||||||
|
@ -55,5 +52,33 @@ mybatis-plus:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
wx:
|
||||||
|
mini:
|
||||||
|
appId: wx3f968a09e31d6bed
|
||||||
|
appSecret: 0b23498d19665dc323efdd3ed5367041
|
||||||
|
|
||||||
|
pay:
|
||||||
|
#应用id(小程序id)
|
||||||
|
appId: wx61b63e27bddf4ea2
|
||||||
|
#商户号
|
||||||
|
merchantId: 1700326544
|
||||||
|
# #商户API私钥
|
||||||
|
# privateKeyPath: apiclient_key.pem
|
||||||
|
#商户证书序列号
|
||||||
|
merchantSerialNumber: 6DC8953AB741D309920DA650B92F837BE38A2757
|
||||||
|
# #商户APIv3密钥
|
||||||
|
# apiV3Key: fbemuj4Xql7CYlQJAoTEPYxvPSNgYT2t
|
||||||
|
#通知地址
|
||||||
|
notifyUrl: https://winning-mouse-internally.ngrok-free.app
|
||||||
|
#微信服务器地址
|
||||||
|
domain: https://api.mch.weixin.qq.com
|
||||||
|
#商户APIv2密钥
|
||||||
|
apiV2Key: cvsOH6TgbbdNUUqFJyLmWGaIEKoSqANg
|
||||||
|
#商户API证书
|
||||||
|
certificatePath: static/apiclient_cert.p12
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
knife4j:
|
knife4j:
|
||||||
enable: true
|
enable: true
|
BIN
src/main/resources/lib/bcprov-ext-jdk15to18-165.jar
Normal file
BIN
src/main/resources/lib/bcprov-ext-jdk15to18-165.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/commons-beanutils.jar
Normal file
BIN
src/main/resources/lib/commons-beanutils.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/commons-codec-1.14.jar
Normal file
BIN
src/main/resources/lib/commons-codec-1.14.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/commons-collections-3.1.jar
Normal file
BIN
src/main/resources/lib/commons-collections-3.1.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/commons-lang-2.1.jar
Normal file
BIN
src/main/resources/lib/commons-lang-2.1.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/commons-logging.jar
Normal file
BIN
src/main/resources/lib/commons-logging.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/ezmorph-1.0.6.jar
Normal file
BIN
src/main/resources/lib/ezmorph-1.0.6.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/httpclient-4.5.6.jar
Normal file
BIN
src/main/resources/lib/httpclient-4.5.6.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/httpcore-4.4.6.jar
Normal file
BIN
src/main/resources/lib/httpcore-4.4.6.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/jackson-annotations-2.9.3.jar
Normal file
BIN
src/main/resources/lib/jackson-annotations-2.9.3.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/jackson-core-2.9.3.jar
Normal file
BIN
src/main/resources/lib/jackson-core-2.9.3.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/jackson-databind-2.9.3.jar
Normal file
BIN
src/main/resources/lib/jackson-databind-2.9.3.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/javax.websocket-api-1.1.jar
Normal file
BIN
src/main/resources/lib/javax.websocket-api-1.1.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/json-lib-2.2.3-jdk13.jar
Normal file
BIN
src/main/resources/lib/json-lib-2.2.3-jdk13.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/log4j-1.2.17.jar
Normal file
BIN
src/main/resources/lib/log4j-1.2.17.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/okhttp-3.2.0.jar
Normal file
BIN
src/main/resources/lib/okhttp-3.2.0.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/slf4j-api-1.7.21.jar
Normal file
BIN
src/main/resources/lib/slf4j-api-1.7.21.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/slf4j-log4j12-1.7.21.jar
Normal file
BIN
src/main/resources/lib/slf4j-log4j12-1.7.21.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/wechatpay-apache-httpclient-0.2.2.jar
Normal file
BIN
src/main/resources/lib/wechatpay-apache-httpclient-0.2.2.jar
Normal file
Binary file not shown.
BIN
src/main/resources/lib/xom-1.2.5.jar
Normal file
BIN
src/main/resources/lib/xom-1.2.5.jar
Normal file
Binary file not shown.
BIN
src/main/resources/static/apiclient_cert.p12
Normal file
BIN
src/main/resources/static/apiclient_cert.p12
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user