From d0b51c6d6f2b7a530c0557b6279cc6dfced223cf Mon Sep 17 00:00:00 2001 From: zhubaomin <470473919@qq.com> Date: 星期日, 27 四月 2025 19:01:04 +0800 Subject: [PATCH] 各轮灌组开阀时间提前10分钟,第一组除外,改为配置文件设置 --- pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java | 532 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 532 insertions(+), 0 deletions(-) diff --git a/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java new file mode 100644 index 0000000..db69d4c --- /dev/null +++ b/pipIrr-platform/pipIrr-web/pipIrr-web-wechat/src/main/java/com/dy/pipIrrWechat/util/PayHelper.java @@ -0,0 +1,532 @@ +package com.dy.pipIrrWechat.util; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.dy.common.webUtil.BaseResponse; +import com.dy.common.webUtil.BaseResponseUtils; +import com.dy.pipIrrGlobal.pojoSe.SeVirtualCard; +import com.dy.pipIrrGlobal.voSe.VoOrders; +import com.dy.pipIrrWechat.result.WechatResultCode; +import com.dy.pipIrrWechat.virtualCard.VirtualCardSv; +import com.dy.pipIrrWechat.wechatpay.PayInfo; +import com.dy.pipIrrWechat.wechatpay.dto.Refund; +import com.dy.pipIrrWechat.wechatpay.dto.RefundRequest; +import com.dy.pipIrrWechat.wechatpay.dto.RefundResponse; +import com.dy.pipIrrWechat.wechatpay.dto.ToRefund; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; + +import javax.crypto.NoSuchPaddingException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.*; + +/** + * @author ZhuBaoMin + * @date 2024-07-15 10:11 + * @LastEditTime 2024-07-15 10:11 + * @Description + */ + +@Component +@RequiredArgsConstructor +public class PayHelper { + private final VirtualCardSv virtualCardSv; + private final RestTemplateUtil restTemplateUtil; + + private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + + private String checkSessionUrl = PayInfo.checkSessionUrl; + private String tokenUrl = PayInfo.tokenUrl; + private String resetUserSessionKeyUrl = PayInfo.resetUserSessionKeyUrl; + private String notifyUrl = PayInfo.notifyUrl; + private String schema = PayInfo.schema; + private String refundUrl = PayInfo.refundUrl; + + // 骞冲彴璇佷功鍏挜 + public Map<String, Certificate> CERTIFICATE_MAP = new HashMap(); + + /** + * 鑾峰彇32浣嶉殢鏈哄瓧绗︿覆 + * @return 闅忔満涓� + */ + public String generateRandomString() { + Random random = new Random(); + StringBuilder sb = new StringBuilder(32); + for (int i = 0; i < 32; i++) { + int index = random.nextInt(CHARACTERS.length()); + sb.append(CHARACTERS.charAt(index)); + } + return sb.toString(); + } + + /** + * 鑾峰彇鍟嗘埛璇佷功绉侀挜瀵硅薄 + * @param certFileBs 绉侀挜鏂囦欢鍐呭 + * @return 绉侀挜瀵硅薄 + * @throws IOException + public PrivateKey getPrivateKey(String filename) throws IOException { + String content = new String(Files.readAllBytes(Paths.get(filename)), "utf-8"); + try { + String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s+", ""); + KeyFactory kf = KeyFactory.getInstance("RSA"); + return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("褰撳墠Java鐜涓嶆敮鎸丷SA", e); + } catch (InvalidKeySpecException e) { + throw new RuntimeException("鏃犳晥鐨勫瘑閽ユ牸寮�"); + } + }*/ + public PrivateKey getPrivateKey(byte[] certFileBs) throws IOException { + String content = new String(certFileBs, "utf-8"); + try { + String privateKey = content.replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replaceAll("\\s+", ""); + KeyFactory kf = KeyFactory.getInstance("RSA"); + return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKey))); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("褰撳墠Java鐜涓嶆敮鎸丷SA", e); + } catch (InvalidKeySpecException e) { + throw new RuntimeException("鏃犳晥鐨勫瘑閽ユ牸寮�"); + } + } + + /** + * 妫�楠岀櫥褰曟�� + * @param appid 灏忕▼搴� appId + * @param secret 灏忕▼搴� appSecret + * @param openid 鐢ㄦ埛鍞竴鏍囪瘑绗� + * @param sessionKey 浼氳瘽瀵嗛挜 + * @return + * @throws IOException + */ + public JSONObject checkSessionKey(String appid, String secret, String openid, String sessionKey) throws IOException, NoSuchAlgorithmException, InvalidKeyException { + String accessToken = ""; + Integer expiresIn = 0; + String signature = HmacSha256.getSignature(sessionKey, ""); + String sigMethod = "hmac_sha256"; + + JSONObject job_token = getAccessToken(appid, secret); + if(job_token != null) { + accessToken = job_token.getString("access_token"); + expiresIn = job_token.getInteger("expires_in"); + } + + Map<String, Object> queryParams = new HashMap<>(); + queryParams.put("access_token", accessToken); + queryParams.put("openid", openid); + queryParams.put("signature", signature); + queryParams.put("sig_method", sigMethod); + Map<String, String> headerParams = new HashMap<>(); + JSONObject result = restTemplateUtil.get(checkSessionUrl, queryParams, headerParams); + return result; + } + + /** + * 閲嶇疆鐧诲綍鎬� + * @param appid 灏忕▼搴� appId + * @param secret 灏忕▼搴� appSecret + * @param openid 鐢ㄦ埛鍞竴鏍囪瘑绗� + * @param sessionKey 浼氳瘽瀵嗛挜 + * @return + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + * @throws IOException + */ + public JSONObject resetUserSessionKey(String appid, String secret, String openid, String sessionKey) throws NoSuchAlgorithmException, InvalidKeyException, IOException { + String accessToken = ""; + Integer expiresIn = 0; + String signature = HmacSha256.getSignature(sessionKey, ""); + String sigMethod = "hmac_sha256"; + + JSONObject job_token = getAccessToken(appid, secret); + if(job_token != null) { + accessToken = job_token.getString("access_token"); + expiresIn = job_token.getInteger("expires_in"); + } + + Map<String, Object> queryParams = new HashMap<>(); + queryParams.put("access_token", accessToken); + queryParams.put("openid", openid); + queryParams.put("signature", signature); + queryParams.put("sig_method", sigMethod); + Map<String, String> headerParams = new HashMap<>(); + JSONObject result = restTemplateUtil.get(resetUserSessionKeyUrl, queryParams, headerParams); + return result; + } + + /** + * 鑾峰彇鎺ュ彛璋冪敤鍑嵁 + * @param appid 灏忕▼搴� appId + * @param secret 灏忕▼搴� appSecret + * @return 鍑嵁鍙婂嚟鎹湁鏁堟椂闂� + * @throws IOException + */ + public JSONObject getAccessToken(String appid, String secret) throws IOException { + Map<String, Object> queryParams = new HashMap<>(); + queryParams.put("grant_type", "client_credential"); + queryParams.put("appid", appid); + queryParams.put("secret", secret); + Map<String, String> headerParams = new HashMap<>(); + JSONObject job_result = restTemplateUtil.get(tokenUrl, queryParams, headerParams); + return job_result; + } + + /** + * 鏋勯�犵鍚嶄覆_涓嬪崟 + * @param method HTTP璇锋眰鏂规硶 + * @param url URL + * @param timestamp 鏃堕棿鎴� + * @param nonceStr 闅忔満涓� + * @param body 鎶ユ枃涓婚 + * @return 绛惧悕涓� + */ + public String buildMessage_order(String method, String url, long timestamp, String nonceStr, String body) { + return method + "\n" + + url + "\n" + + timestamp + "\n" + + nonceStr + "\n" + + body + "\n"; + } + + /** + * 鏋勯�犵鍚嶄覆_鍐嶆涓嬪崟 + * @param appid 灏忕▼搴忓敮涓�鏍囪瘑 + * @param timestamp 鏃堕棿鎴� + * @param nonceStr 闅忔満涓� + * @param pkg package + * @return 绛惧悕涓� + */ + public String buildMessage_signAgain(String appid, String timestamp, String nonceStr, String pkg) { + return appid + "\n" + + timestamp + "\n" + + nonceStr + "\n" + + pkg + "\n"; + } + + /** + * 绛惧悕 + * @param message 琚鍚嶄俊鎭� + * @param certBs 绉侀挜璇佷功鏂囦欢鍐呭 + * @return signature绛惧悕鍊硷紝绛惧悕淇℃伅涓殑涓�椤癸紝鍙備笌鐢熸垚绛惧悕淇℃伅 + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + * @throws SignatureException + * @throws IOException + public String sign(byte[] message, String certFileName) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException { + Signature sign = Signature.getInstance("SHA256withRSA"); + sign.initSign(getPrivateKey(certFileName)); + sign.update(message); + return Base64.getEncoder().encodeToString(sign.sign()); + }*/ + public String sign(byte[] message, byte[] certBs) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException, IOException, Exception { + Signature sign = Signature.getInstance("SHA256withRSA"); + sign.initSign(getPrivateKey(certBs)); + sign.update(message); + return Base64.getEncoder().encodeToString(sign.sign()); + } + + /** + * 鑾峰彇绛惧悕淇℃伅 + * @param method + * @param url + * @param body + * @return 绛惧悕淇℃伅锛孒TTP澶翠腑鐨勭鍚嶄俊鎭� + * HTTP澶达細Authorization: 璁よ瘉绫诲瀷 绛惧悕淇℃伅 + * 璁よ瘉绫诲瀷锛學ECHATPAY2-SHA256-RSA2048 + public String getToken(String method, String url, String body, String nonceStr, Long timestamp, String certFileName) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException, NoSuchPaddingException { + String message = buildMessage_order(method, url, timestamp, nonceStr, body); + String signature = sign(message.getBytes("utf-8"), certFileName); + + return "mchid=\"" + PayInfo.mchid + "\"," + + "nonce_str=\"" + nonceStr + "\"," + + "timestamp=\"" + timestamp + "\"," + + "serial_no=\"" + PayInfo.serial_no + "\"," + + "signature=\"" + signature + "\""; + }*/ + public String getToken(String method, String url, String body, String nonceStr, Long timestamp, byte[] certFileBs) throws NoSuchAlgorithmException, InvalidKeySpecException, IOException, SignatureException, InvalidKeyException, Exception { + String message = buildMessage_order(method, url, timestamp, nonceStr, body); + String signature = sign(message.getBytes("utf-8"), certFileBs); + + return "mchid=\"" + PayInfo.mchid + "\"," + + "nonce_str=\"" + nonceStr + "\"," + + "timestamp=\"" + timestamp + "\"," + + "serial_no=\"" + PayInfo.serial_no + "\"," + + "signature=\"" + signature + "\""; + } + + /** + * 鏋勯�犻獙閫犵鍚嶄覆 + * @param wechatpayTimestamp 璇锋眰澶翠腑杩斿洖鐨勬椂闂存埑 + * @param wechatpayNonce 璇锋眰澶翠腑杩斿洖鐨勯殢鏈轰覆 + * @param boey 璇锋眰杩斿洖鐨刡ody + * @return signatureStr鏋勯�犵殑楠岀鍚嶄覆 + */ + public String responseSign(String wechatpayTimestamp, String wechatpayNonce, String boey) { + String signatureStr = wechatpayTimestamp + "\n" + + wechatpayNonce + "\n" + + boey + "\n"; + return signatureStr; + } + + /** + * 閲嶆柊涓嬭浇璇佷功 + */ + public void refreshCertificate(byte[] certFileBs) throws GeneralSecurityException, IOException , Exception { + String method = "GET"; + String httpUrl = "/v3/certificates"; + String nonceStr = generateRandomString(); + Long timestamp = System.currentTimeMillis() / 1000; + + String header = PayInfo.schema + " " + getToken(method, httpUrl, "", nonceStr, timestamp, certFileBs); + + Map<String, String> headers = new HashMap<>(); + headers.put("Authorization", header); + headers.put("Accept", "application/json"); + //headers.put("User-Agent", "https://zh.wikipedia.org/wiki/User_agent"); + + JSONObject job_result = restTemplateUtil.getHeaders(PayInfo.certificates,null, headers); + JSONObject job_headers = job_result.getJSONObject("headers"); + + String wechatpayNonce = job_headers.getJSONArray("Wechatpay-Nonce").getString(0); + String wechatpaySerial = job_headers.getJSONArray("Wechatpay-Serial").getString(0); + String signature_h = job_headers.getJSONArray("Wechatpay-Signature").getString(0); + String signatureType_h = job_headers.getJSONArray("Wechatpay-Signature-Type").getString(0); + String wechatpayTimestamp = job_headers.getJSONArray("Wechatpay-Timestamp").getString(0); + + JSONObject job_body = job_result.getJSONObject("body"); + if(job_body != null) { + JSONArray array = job_body.getJSONArray("data"); + if(array != null && array.size() > 0) { + for(int i = 0; i < array.size(); i++) { + JSONObject job_data = array.getJSONObject(i); + String certificateSerial = job_data.getString("serial_no"); + String effective_time = job_data.getString("effective_time"); + String expire_time = job_data.getString("expire_time"); + JSONObject job_certificate = job_data.getJSONObject("encrypt_certificate"); + String algorithm = job_certificate.getString("algorithm"); + String nonce = job_certificate.getString("nonce"); + String associated_data = job_certificate.getString("associated_data"); + String ciphertext = job_certificate.getString("ciphertext"); + + //瀵硅瘉涔﹀瘑鏂囪繘琛岃В瀵嗗緱鍒板钩鍙拌瘉涔﹀叕閽� + String publicKey = AesUtil.decryptToString(PayInfo.key.getBytes("utf-8"), associated_data.getBytes("utf-8"), nonce.getBytes("utf-8"), ciphertext); + + // 灏嗗钩鍙板叕閽ュ瓧绗︿覆杞垚Certificate瀵硅薄 + final CertificateFactory cf = CertificateFactory.getInstance("X509"); + ByteArrayInputStream inputStream = new ByteArrayInputStream(publicKey.getBytes(StandardCharsets.UTF_8)); + Certificate certificate = null; + try { + certificate = cf.generateCertificate(inputStream); + } catch (CertificateException e) { + e.printStackTrace(); + } + + // 鍝嶅簲澶磋瘉涔﹀簭鍙蜂笌鍝嶅簲浣撹瘉涔﹀簭鍒楀彿涓�鑷达紝涓旀椂闂村樊灏忎簬5鍒嗛挓鏃舵墠灏嗚瘉涔﹀瓨鍌╩ap + Long timeDiff = (System.currentTimeMillis() / 1000 - Long.parseLong(wechatpayTimestamp))/60; + if(wechatpaySerial.equals(certificateSerial) && timeDiff <= 5) { + // 璇佷功鏀惧叆MAP + CERTIFICATE_MAP.put(certificateSerial, certificate); + } + } + } + } + } + + /** + * 浣跨敤寰俊骞冲彴璇佷功杩涜鍝嶅簲楠岀 + * @param wechatpaySerial 鏉ヨ嚜鍝嶅簲澶寸殑寰俊骞冲彴璇佷功搴忓垪鍙� + * @param signatureStr 鏋勯�犵殑楠岀鍚嶄覆 + * @param wechatpaySignature 鏉ヨ嚜鍝嶅簲澶寸殑寰俊骞冲彴绛惧悕 + * @return + * @throws NoSuchAlgorithmException + * @throws InvalidKeyException + * @throws SignatureException + */ + public Boolean responseSignVerify(String wechatpaySerial, String signatureStr, String wechatpaySignature, byte[] certFileBs) throws Exception { + if(CERTIFICATE_MAP.isEmpty() || !CERTIFICATE_MAP.containsKey(wechatpaySerial)) { + CERTIFICATE_MAP.clear(); + refreshCertificate(certFileBs); + } + Certificate certificate = (Certificate)CERTIFICATE_MAP.get(wechatpaySerial); + if(certificate == null) { + return false; + } + + // 鑾峰彇鍏挜 + PublicKey publicKey = certificate.getPublicKey(); + + // 鍒濆鍖朣HA256withRSA鍓嶉潰鍣� + Signature signature = Signature.getInstance("SHA256withRSA"); + // 鐢ㄥ井淇″钩鍙板叕閽ュ鍓嶉潰鍣ㄨ繘琛屽垵濮嬪寲 + signature.initVerify(certificate); + + // 灏嗘瀯閫犵殑楠岀鍚嶄覆鏇存柊鍒扮鍚嶅櫒涓� + signature.update(signatureStr.getBytes(StandardCharsets.UTF_8)); + + // 璇锋眰澶翠腑寰俊鏈嶅姟鍣ㄨ繑鍥炵殑绛惧悕鐢˙ase64瑙g爜锛屼娇鐢ㄧ鍚嶅櫒杩涜楠岃瘉 + boolean valid = signature.verify(Base64.getDecoder().decode(wechatpaySignature)); + return valid; + } + + + /** + * 鑾峰彇寰呴��娆惧璞″垪琛� + * 寰呴��娆惧璞″寘鍚鍗曞彿鍜屽彲閫�娆鹃噾棰� + * 璁㈠崟瀵硅薄鍖呭惈璁㈠崟鍙枫�佸厖鍊奸噾棰濄�佸厖鍊煎畬鎴愭椂闂� + * 1. 鏍规嵁铏氭嫙鍗″彿鍒拌櫄鎷熷崱琛ㄤ腑鍙栧嚭璇ュ崱浣欓 + * 2. 鏍规嵁铏氭嫙鍗″彿鍒板厖鍊艰〃鍙栧嚭璁㈠崟瀵硅薄鍒楄〃 + * @param virtualId + * @param refundAmount + * @return + */ + public List<ToRefund> getToRefunds(Long virtualId, Integer refundAmount) { + ToRefund toRefund = new ToRefund(); + List<ToRefund> list = new ArrayList<>(); + Double money = 0d; + + // 鏍规嵁铏氭嫙鍗″彿鑾峰彇褰撳墠铏氭嫙鍗′綑棰� + SeVirtualCard seVirtualCard = virtualCardSv.selectVirtuCardById(virtualId); + if(seVirtualCard != null) { + money = seVirtualCard.getMoney(); + } + + // 瑕侀��閲戦澶т簬璇ュ崱浣欓锛岃繑鍥炵┖鍒楄〃 + if(refundAmount > money) { + return list; + } + + // 鏍规嵁铏氭嫙鍗″彿鑾峰彇璁㈠崟鍒楄〃锛堜粎闄愬厖鍊兼垚鍔熺殑锛� + List<VoOrders> list_Orders = virtualCardSv.selectOrders(virtualId); + // 閬嶅巻璁㈠崟鍒楄〃锛岃幏鍙� + if(list_Orders != null && list_Orders.size() > 0) { + JSONArray array_Orders = (JSONArray) JSON.toJSON(list_Orders); + for(int i = 0; i < array_Orders.size(); i++) { + JSONObject job_order = array_Orders.getJSONObject(i); + String orderNumber = job_order.getString("orderNumber"); + Integer rechargeAmount = job_order.getInteger("rechargeAmount"); + Date rechargeTime = job_order.getDate("rechargeTime"); + + // 璁$畻鍏呭�艰嚦浠婃椂闂村樊锛堝垎閽燂級 + Long timestamp_Recharge = rechargeTime.getTime() / 1000; + Long timestamp_Current = System.currentTimeMillis() / 1000; + Long timeDiff_Minute = (timestamp_Current - timestamp_Recharge)/60; + + // 鑾峰彇璇ヨ鍗曞凡閫�娆剧瑪鏁� + Integer refundCount = 0; + List<Integer> list_RefundAmount = virtualCardSv.selectRefundAmount(orderNumber); + if(list_RefundAmount != null && list_RefundAmount.size() > 0) { + refundCount = list_RefundAmount.size(); + } + + // 鍏呭�艰嚦浠婃湭瓒呰繃涓�骞翠笖璇ヨ鍗曢��娆炬�绘鏁版湭瓒呰繃50娆� + if(timeDiff_Minute/(365*24*60) >= 1 && (refundCount + 1) > 50) + return list; + + /** + * 1. 濡傛灉瑕侀��閲戦灏忎簬褰撳墠璁㈠崟鐨勫厖鍊奸噾棰濓紝瑕侀��閲戦鍗充负搴旈��閲戦骞惰繑鍥� + * 2. 濡傛灉瑕佹帹閲戦澶т簬褰撳墠璁㈠崟鍏呭�奸噾棰濓紝褰撳墠璁㈠崟鍏呭�奸噾棰濆嵆涓哄簲閫�閲戦 + * a. 鐢熸垚搴旈��娆惧璞� + * b. 璁$畻鏂扮殑浣欓 + * c. 閲戣挏鏂扮殑瑕侀��娆鹃噾棰� + * d. 濡傛灉瑕侀��閲戦澶т簬0锛岄亶鍘嗕笅涓�涓鍗� + */ + if(refundAmount <= rechargeAmount) { + toRefund = new ToRefund(); + toRefund.setOrderNumber(orderNumber); + toRefund.setRefundAmount(refundAmount); + list.add(toRefund); + // 璁$畻鏂扮殑浣欓鍜屾柊鐨勮閫�閲戦 + money = money - refundAmount; + refundAmount = refundAmount - refundAmount; + return list; + }else { + toRefund = new ToRefund(); + toRefund.setOrderNumber(orderNumber); + toRefund.setRefundAmount(rechargeAmount); + list.add(toRefund); + // 璁$畻鏂扮殑浣欓鍜屾柊鐨勮閫�閲戦 + money = money - rechargeAmount; + refundAmount = refundAmount - rechargeAmount; + if(refundAmount > 0) { + continue; + }else { + return list; + } + } + } + } + return list; + } + + /** + * 閫�娆剧敵璇凤紝璋冪敤寰俊鏀粯閫�娆剧敵璇锋帴鍙� + * @param po 閫�娆捐姹傚璞★紝鍖呭惈璁㈠崟鍙枫�侀��娆惧崟鍙枫�侀��娆鹃噾棰� + * @return + * @throws NoSuchPaddingException + * @throws NoSuchAlgorithmException + * @throws InvalidKeySpecException + * @throws IOException + * @throws SignatureException + * @throws InvalidKeyException + */ + public BaseResponse<Boolean> refunds(Refund po, byte[] certFileBs) throws SignatureException, InvalidKeyException, Exception{ + String tradeNo = po.getTradeNo(); + String refundNo = po.getRefundNo(); + Integer refund = po.getRefund(); + + // 鐢熸垚body + Double total = virtualCardSv.getRechargeAmountByOrderNumber(tradeNo); + RefundRequest.Amount amount = new RefundRequest.Amount(); + amount.setRefund(refund); + amount.setTotal(total); + amount.setCurrency("CNY"); + + RefundRequest refundRequest = new RefundRequest(); + refundRequest.setOut_trade_no(tradeNo); + refundRequest.setOut_refund_no(refundNo); + refundRequest.setNotify_url(notifyUrl); + refundRequest.setAmount(amount); + + // 鐢熸垚header + String nonceStr = generateRandomString(); + Long timestamp = System.currentTimeMillis() / 1000; + + String method = "POST"; + String httpUrl = "/v3/refund/domestic/refunds"; + + String body = JSONObject.toJSONString(refundRequest); + String header = schema + " " + getToken(method, httpUrl, body, nonceStr, timestamp, certFileBs); + + Map<String, String> headers = new HashMap<>(); + headers.put("Authorization", header); + headers.put("Accept", "application/json"); + headers.put("Content-Type", "application/json"); + + JSONObject job_refundResponse = restTemplateUtil.post(PayInfo.refundUrl, body, headers); + RefundResponse refundResponse = JSON.parseObject(job_refundResponse.toJSONString(), RefundResponse.class); + + String status = refundResponse.getStatus(); + if(status != null && status.equals("SUCCESS")) { + // 閫�娆剧敵璇峰凡鍙楃悊 + return BaseResponseUtils.buildSuccess(true) ; + } else if(status != null && status.equals("PROCESSING")) { + // 閫�娆惧鐞嗕腑 + return BaseResponseUtils.buildFail(WechatResultCode.PROCESSING.getMessage()); + } else { + // 閫�娆惧紓甯� + return BaseResponseUtils.buildError(WechatResultCode.ABNORMAL.getMessage()); + } + } +} -- Gitblit v1.8.0