话不多说 上代码;
//支付密钥算法
public static String calcPaySig(String uri, String postBody, String appKey) {
String needSignMsg = uri + "&" + postBody;
try {
Mac sha256Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(appKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256Hmac.init(secretKey);
byte[] hmacBytes = sha256Hmac.doFinal(needSignMsg.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte hmacByte : hmacBytes) {
String hex = Integer.toHexString(0xff & hmacByte);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
return null;
}
}
// 签名密钥算法
public static String calcSignature(String postBody, String sessionKey) {
String needSignMsg = postBody;
try {
Mac sha256Hmac = Mac.getInstance("HmacSHA256");
SecretKeySpec secretKey = new SecretKeySpec(sessionKey.getBytes(StandardCharsets.UTF_8), "HmacSHA256");
sha256Hmac.init(secretKey);
byte[] hmacBytes = sha256Hmac.doFinal(needSignMsg.getBytes(StandardCharsets.UTF_8));
StringBuilder hexString = new StringBuilder();
for (byte hmacByte : hmacBytes) {
String hex = Integer.toHexString(0xff & hmacByte);
if (hex.length() == 1) hexString.append('0');
hexString.append(hex);
}
return hexString.toString();
} catch (NoSuchAlgorithmException | InvalidKeyException e) {
e.printStackTrace();
return null;
}
}
业务代码:
/**
* 虚拟支付2.0
* pay_v2.getBalance
*
* @param dto
* @return
*/
public MidasBalanceV2VO balanceV2(MidasBalanceV2DTO dto) {
OrderInfo orderInfo = orderInfoRepo.getByOrderNumber(dto.getOrderNumber());
String sessionKey = wxApiSessionKeyAndOpenIdRedis.retrieve(dto.getOpenid())[0];
if (Objects.isNull(orderInfo))throw new AppException(ErrorCode.ORDER_INFO_NO_EXIST);
WxAppletConfig wxConfig = gameAppRepo.getByAppNumber(dto.getAppNumber()).getWxAppletConfig();
if (Objects.isNull(wxConfig) || StringUtils.isBlank(wxConfig.getWxAppletAppId()) || StringUtil.isBlank(wxConfig.getWxAppletSecret())) {
throw new AppException(ErrorCode.SYS_ERROR.code(), "应用未配置小程序信息");
}
GetBalanceParamV2 paramV2 = new GetBalanceParamV2(wxConfig.getMidasOfferId(),dto.getOpenid(),dto.getTs(), dto.getZoneId(), wxConfig.getMidasEnv());
String postBody = JsonUtils.Object2Json(paramV2);
String signature = calcSignature(postBody, sessionKey);
String appKey = wxConfig.getMidasSecret();
String paySig = calcPaySig(BALANCE_URI, postBody, appKey);
String accessToken = wxApiService.authGetAccessTokenForMidas(wxConfig.getWxAppletAppId(), wxConfig.getWxAppletSecret());
GetBalanceResultV2 balanceResultV2 = MidasPayUtil.getBalanceV2(signature,paySig,accessToken,postBody);
if(balanceResultV2.getErrCode() != 0){
log.error("【订单编号:{}】;调用微信接口出错:余额不足",orderInfo.getOrderNumber());
throw new AppException(ErrorCode.PAY_WECHAT_INTERFACE_ERROR.code(), balanceResultV2.getErrMsg());
}
return getMidasBalanceV2VO(orderInfo, wxConfig, balanceResultV2);
}
注意再经过wx.auth2Session()获取的wx.code只能使用一次,否者会出现 code been used..错误。所以再微信授权的时候把auth2Session返回的结果集中的sessionKey丢再redis中,通过hash结构来存储取出。
另外切记切记postbody中的Filed一定要加下划线来请求 !! (被这个无关紧要的问题给卡住了两天,最后发现是offerId要改为offer_id 微信那边才能识别出你的offer_id,不然识别不出!)
getBanlanceV2(2.0版本)
/**
* 虚拟支付2.0 【查询余额】
*
* 获取余额 pay_getBalance
* POST https://api.weixin.qq.com/wxa/game/getbalance?access_token=ACCESS_TOKEN&signature=SIGNATURE&sig_method=SIG_METHOD&pay_sig=PAY_SIGNATURE
*
*/
public static GetBalanceResultV2 getBalanceV2(String signature, String paySig, String accessToken, String postBody) {
// 0 米大师正式环境 1 米大师沙箱环境 https://api.weixin.qq.com/wxa/game/
String url = MIDAS_API_BASE_URL + "getbalance"
+ "?access_token="+accessToken
+ "&signature="+signature
+ "&pay_sig="+paySig;
try {
log.info("微信API:{}",url);
HashMap<String, String> headers = new HashMap<>();
headers.put("Content-Type", "application/json");
log.info("body:{}",postBody);
String postForm = HttpUtil.post(url, postBody, headers);
log.info("返回参数:{}", postForm);
return JSONObject.parseObject(postForm, GetBalanceResultV2.class);
} catch (Exception e) {
log.info("微信API:{},异常信息:{}", url, e);
throw new AppException(ErrorCode.SYS_ERROR.code(), e.getMessage());
}
}
大家就作为一个参考吧!