微信支付V3之投诉回调API封装

大家好,我是梦辛工作室的灵,近期在制作相关软件的过程中,有需要用到对微信商户号的投诉风险合规,第一次搞这个还是踩了不少坑,然后为了方便使用做了以下封装便于大家使用,其实也不难,主要怪自己没有去仔细看微信提供的指导(在 官方提供的 wechatpay-apache-httpclient-0.2.2.jar 的基础上继续简化的),下来就讲下怎么写吧

先准备好以下相关资料:
1.商户号 编号
2.商户号 ApiV3 秘钥,需要在 微信商户号后台设置
3.商户号证书私钥,下载商户号 证书时会有那个 apiclient_key.pem 文件就是它
4.商户号证书序列号,这个可以在 微信商户号证书管理后台查看

准备好以上资料后就可以开始写了
第一步:加载证书,获取到httpCilent对象:

public void setup() {

		if (!doCheckParam()) {
			isStep = false;
			return;
		}

		try {

			privateKey = new String(Files.readAllBytes(Paths.get(privateKeyFilePath)), "utf-8");

			// 加载商户私钥(privateKey:私钥字符串)
			merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));

			// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
			AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
					new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),
					apiV3Key.getBytes("utf-8"));

			// 初始化httpClient
			httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, merchantPrivateKey)
					.withValidator(new WechatPay2Validator(verifier)).build();

			isStep = true;

		} catch (Exception e) {
			// TODO: handle exception
			errorHint = errorHint.toString();
			isStep = false;
		}

	}

第二步:发起创建投诉回调通知 ,其他操作类同

/**
	 * 创建投诉回调通知
	 * 
	 * @param url
	 *            回调地址
	 * @return
	 * @throws Exception
	 */
	public String CreateComplaintsNotify(String url) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications");
		JSONObject dataJSON = new JSONObject();
		dataJSON.put("url", url);

		StringEntity entity = new StringEntity(dataJSON.toString());
		entity.setContentType("application/json");
		httpPost.setEntity(entity);
		httpPost.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpPost);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

这里需要注意的是:微信提供的这个 API封装(wechatpay-apache-httpclient-0.2.2.jar)在发起请求时已经自带了 Authorization Header,所以不用再去添加这个Header,不然会报错,楼主在这里被坑了好久,翻了不好文档才找到

还有就是如果有出现 java.security.InvalidKeyException: Illegal key size WechatPayHttpClientBuild 错误的话,请注意 java版本,如果在 java 8u 162 以下的话,请更换 java 版本 ,必须要在 java 8u 162 以上才可以 , 早期的java 运行 限制了 JCE支持的秘钥长度,即默认不支持256位的AES,这里楼主也被坑了好早,试过好多方法才找到,换来是java版本低了

下面是所有代码示例:

package com.mx.util;

public class WeChatAPIV3 {

	CloseableHttpClient httpClient;

	CloseableHttpClient httpNoSignPayClient;

	String mchId = "";
	String mchSerialNo = "";
	String apiV3Key = "";
	String privateKeyFilePath = "";

	String privateKey = "";
	String certKeyFilePath = "";
	PrivateKey merchantPrivateKey;
	PublicKey merchantPublicKey;
	PublicKey pingtaiPublicKey;
	String errorHint = "";

	public String getErrorHint() {
		return errorHint;
	}

	public void setErrorHint(String errorHint) {
		this.errorHint = errorHint;
	}

	public boolean isStep() {
		return isStep;
	}

	long lastUseTime = 0;

	public long getLastUseTime() {
		return lastUseTime;
	}

	public void setLastUseTime(long lastUseTime) {
		this.lastUseTime = lastUseTime;
	}

	public String getCertKeyFilePath() {
		return certKeyFilePath;
	}

	public void setCertKeyFilePath(String certKeyFilePath) {
		this.certKeyFilePath = certKeyFilePath;
	}

	public String getMchId() {
		return mchId;
	}

	public void setMchId(String mchId) {
		this.mchId = mchId;
	}

	public String getMchSerialNo() {
		return mchSerialNo;
	}

	public void setMchSerialNo(String mchSerialNo) {
		this.mchSerialNo = mchSerialNo;
	}

	public String getApiV3Key() {
		return apiV3Key;
	}

	public void setApiV3Key(String apiV3Key) {
		this.apiV3Key = apiV3Key;
	}

	public String getPrivateKeyFilePath() {
		return privateKeyFilePath;
	}

	public void setPrivateKeyFilePath(String privateKeyFilePath) {
		this.privateKeyFilePath = privateKeyFilePath;
	}

	private boolean isStep = false;

	public WeChatAPIV3() {

	}

	public WeChatAPIV3(String mchId, String mchSerialNo, String apiV3Key, String privateKeyFilePath) {
		this.mchId = mchId;
		this.mchSerialNo = mchSerialNo;
		this.apiV3Key = apiV3Key;
		this.privateKeyFilePath = privateKeyFilePath;

	}

	public String rsaDecryptOAEP(String ciphertext) throws BadPaddingException, IOException {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		if (merchantPrivateKey == null) {
			errorHint = "未成功加载私钥";
			return null;
		}

		try {

			Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");

			cipher.init(Cipher.DECRYPT_MODE, merchantPrivateKey);

			byte[] data = Base64.getDecoder().decode(ciphertext);
			return new String(cipher.doFinal(data), "utf-8");
		} catch (NoSuchPaddingException | NoSuchAlgorithmException e) {
			throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
		} catch (InvalidKeyException e) {
			throw new IllegalArgumentException("无效的私钥", e);
		} catch (BadPaddingException | IllegalBlockSizeException e) {
			throw new BadPaddingException("解密失败");
		}
	}

	public void loadPTCert(String certKey) throws UnsupportedEncodingException {
		pingtaiPublicKey = PemUtil.loadCertificate(new ByteArrayInputStream(certKey.getBytes("utf-8"))).getPublicKey();
	}

	public String rsaEncryptOAEP_PT(String message) throws IllegalBlockSizeException, IOException {

		if (pingtaiPublicKey == null) {
			errorHint = "未成功加载公钥";
			return null;
		}

		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
			cipher.init(Cipher.ENCRYPT_MODE, pingtaiPublicKey);

			byte[] data = message.getBytes("utf-8");
			byte[] cipherdata = cipher.doFinal(data);
			return Base64.getEncoder().encodeToString(cipherdata);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
		} catch (InvalidKeyException e) {
			throw new IllegalArgumentException("无效的证书", e);
		} catch (IllegalBlockSizeException | BadPaddingException e) {
			throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
		}
	}

	public String signBySHA256WithRSA(String content) {
		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		if (merchantPrivateKey == null) {
			errorHint = "未成功加载私钥";
			return null;
		}

		try {
			// PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
			// org.apache.commons.codec.binary.Base64.decodeBase64(privateKey));
			// PrivateKey priKey = KeyFactory.getInstance("RSA").generatePrivate(priPKCS8);

			Signature signature = Signature.getInstance("SHA256withRSA");
			signature.initSign(merchantPrivateKey);
			signature.update(content.getBytes("utf-8"));

			return org.apache.commons.codec.binary.Base64.encodeBase64String(signature.sign());
		} catch (Exception e) {
			// 签名失败
			e.printStackTrace();
			return null;
		}
	}

	public String rsaEncryptOAEP(String message) throws IllegalBlockSizeException, IOException {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		if (merchantPublicKey == null) {
			errorHint = "未成功加载公钥";
			return null;
		}

		try {
			Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
			cipher.init(Cipher.ENCRYPT_MODE, merchantPublicKey);

			byte[] data = message.getBytes("utf-8");
			byte[] cipherdata = cipher.doFinal(data);
			return Base64.getEncoder().encodeToString(cipherdata);
		} catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
			throw new RuntimeException("当前Java环境不支持RSA v1.5/OAEP", e);
		} catch (InvalidKeyException e) {
			throw new IllegalArgumentException("无效的证书", e);
		} catch (IllegalBlockSizeException | BadPaddingException e) {
			throw new IllegalBlockSizeException("加密原串的长度不能超过214字节");
		}
	}

	public boolean doCheckParam() {

		return doCheckValue(mchId, mchSerialNo, apiV3Key, privateKeyFilePath, certKeyFilePath);
	}

	public boolean doCheckValue(String... item) {
		for (String each : item) {
			if (each == null || each.length() == 0) {
				errorHint = "缺少必要参数";
				return false;
			}
		}
		return true;
	}

	public void setup() {

		if (!doCheckParam()) {
			isStep = false;
			return;
		}

		try {

			extracted();
//			extractedNew();

			isStep = true;

		} catch (Exception e) {
			errorHint = errorHint.toString();
			isStep = false;
			e.printStackTrace();
		}

	}

	private void extractedNew() throws Exception {

		String certKey = new String(Files.readAllBytes(Paths.get(certKeyFilePath)), "utf-8");

		merchantPublicKey = PemUtil.loadCertificate(new ByteArrayInputStream(certKey.getBytes("utf-8")))
				.getPublicKey();

		privateKey = new String(Files.readAllBytes(Paths.get(privateKeyFilePath)), "utf-8");

		merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));


		CertificatesManager certificatesManager = CertificatesManager.getInstance();
		// 向证书管理器增加需要自动更新平台证书的商户信息
		certificatesManager.putMerchant(mchId, new WechatPay2Credentials(mchId,
				new PrivateKeySigner(mchSerialNo, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
		// ... 若有多个商户号,可继续调用putMerchant添加商户信息

		// 从证书管理器中获取verifier
		Verifier verifier = certificatesManager.getVerifier(mchId);
		WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
				.withMerchant(mchId, mchSerialNo, merchantPrivateKey)
				.withValidator(new WechatPay2Validator(verifier));
		// ... 接下来,你仍然可以通过builder设置各种参数,来配置你的HttpClient

		// 通过WechatPayHttpClientBuilder构造的HttpClient,会自动的处理签名和验签,并进行证书自动更新
		httpClient = builder.build();
	}

	@Deprecated
	private void extracted() throws IOException {
		privateKey = new String(Files.readAllBytes(Paths.get(privateKeyFilePath)), "utf-8");

		String certKey = new String(Files.readAllBytes(Paths.get(certKeyFilePath)), "utf-8");

		// 加载商户私钥(privateKey:私钥字符串)
		merchantPrivateKey = PemUtil.loadPrivateKey(new ByteArrayInputStream(privateKey.getBytes("utf-8")));

		// 加载商户公钥(privateKey:证书字符串)
		merchantPublicKey = PemUtil.loadCertificate(new ByteArrayInputStream(certKey.getBytes("utf-8")))
				.getPublicKey();

		// 加载平台证书(mchId:商户号,mchSerialNo:商户证书序列号,apiV3Key:V3密钥)
		AutoUpdateCertificatesVerifier verifier = new AutoUpdateCertificatesVerifier(
				new WechatPay2Credentials(mchId, new PrivateKeySigner(mchSerialNo, merchantPrivateKey)),
				apiV3Key.getBytes("utf-8"));


		// 初始化httpClient
		httpClient = WechatPayHttpClientBuilder.create().withMerchant(mchId, mchSerialNo, merchantPrivateKey)
				.withValidator(new WechatPay2Validator(verifier)).build();

		WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
				.withMerchant(mchId, mchSerialNo, merchantPrivateKey)
				//设置响应对象无需签名
				.withValidator((response) -> true);

		httpNoSignPayClient = builder.build();


	}


	/**
	 * 查询投诉详情
	 *
	 * @param complaint_id
	 *            投诉单号
	 * @return
	 * @throws Exception
	 */
	public String GetComplaintsInfo(String complaint_id) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpGet httpGet = new HttpGet(
				"https://api.mch.weixin.qq.com/v3/merchant-service/complaints-v2/" + complaint_id);
		httpGet.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpGet);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 查询协商历史
	 *
	 * @param complaint_id
	 *            投诉单号
	 * @param offset
	 *            开始位置
	 * @param limit
	 *            返回数据条数
	 * @return
	 * @throws Exception
	 */
	public String GetComplaintsHis(String complaint_id, int offset, int limit) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpGet httpGet = new HttpGet("https://api.mch.weixin.qq.com/v3/merchant-service/complaints-v2/" + complaint_id
				+ "/negotiation-historys?limit=" + limit + "&offset=" + offset);
		httpGet.setHeader("Accept", "application/json");
		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpGet);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 查询投诉单列表
	 *
	 * @param offset
	 *            开始位置
	 * @param limit
	 *            返回数据条数
	 * @param begin_date
	 *            开始日期 yyyy-MM-dd
	 * @param end_date
	 *            结束日期 yyyy-MM-dd 时间差最大一个月
	 * @return 查询结果
	 * @throws Exception
	 */
	public String GetComplaintsList(int offset, int limit, String begin_date, String end_date) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpGet httpGet = new HttpGet(
				"https://api.mch.weixin.qq.com/v3/merchant-service/complaints-v2?limit=" + limit + "&offset=" + offset
						+ "&begin_date=" + begin_date + "&end_date=" + end_date + "&complainted_mchid=" + mchId);
		httpGet.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpGet);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	public void after() throws IOException {
		httpClient.close();
	}

	/**
	 * 查询通知回调地址
	 * @param
	 * @return
	 * @throws Exception
	 */
	public String queryComplaintsNotify() throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications");
		// 请求URL
		HttpGet httpGet = new HttpGet(uriBuilder.build());
		httpGet.addHeader("Accept", "application/json");


		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpGet);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 创建投诉回调通知
	 *
	 * @param url
	 *            回调地址
	 * @return
	 * @throws Exception
	 */
	public String CreateComplaintsNotify(String url) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications");
		JSONObject dataJSON = new JSONObject();
		dataJSON.put("url", url);

		StringEntity entity = new StringEntity(dataJSON.toString());
		entity.setContentType("application/json");
		httpPost.setEntity(entity);
		httpPost.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpPost);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 更新投诉回调通知
	 *
	 * @param url
	 *            回调通知
	 * @return
	 * @throws Exception
	 */
	public String UpdateComplaintsNotify(String url) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpPut httpPut = new HttpPut("https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications");
		JSONObject dataJSON = new JSONObject();
		dataJSON.put("url", url);

		StringEntity entity = new StringEntity(dataJSON.toString());
		entity.setContentType("application/json");
		httpPut.setEntity(entity);
		httpPut.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpPut);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;

	}

	/**
	 * 删除投诉回调通知地址
	 *
	 * @return
	 * @throws Exception
	 */
	public String DelComplaintsNotify() throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpDelete httpDel = new HttpDelete(
				"https://api.mch.weixin.qq.com/v3/merchant-service/complaint-notifications");
		httpDel.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpDel);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 提交回复
	 *
	 * @param complaint_id
	 *            被投诉单号
	 * @param responseJson
	 *            回复内容
	 * @return
	 * @throws Exception
	 */
	public String ReplyInfo(String complaint_id, JSONObject responseJson) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpPost httpPost = new HttpPost(
				"https://api.mch.weixin.qq.com/v3/merchant-service/complaints-v2/" + complaint_id + "/response");
		// 请求body参数

		responseJson.put("complainted_mchid", mchId);

		StringEntity entity = new StringEntity(responseJson.toString(),"UTF-8");
		entity.setContentType("application/json");
		httpPost.setEntity(entity);
		httpPost.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpPost);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 反馈处理完成
	 *
	 * @param complaint_id
	 *            投诉单号
	 * @return
	 * @throws Exception
	 */
	public String CompleteComplaints(String complaint_id) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpPost httpPost = new HttpPost(
				"https://api.mch.weixin.qq.com/v3/merchant-service/complaints-v2/" + complaint_id + "/complete");
		JSONObject dataJSON = new JSONObject();
		dataJSON.put("complainted_mchid", mchId);

		StringEntity entity = new StringEntity(dataJSON.toString());
		entity.setContentType("application/json");
		httpPost.setEntity(entity);
		httpPost.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpPost);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 上传图片
	 *
	 * @param filePath
	 *            图片路径
	 * @return
	 * @throws Exception
	 */
	public String uploadImg(String filePath) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		URI uri = new URI("https://api.mch.weixin.qq.com/v3/merchant-service/images/upload");
		File file = new File(filePath);

		try (FileInputStream ins1 = new FileInputStream(file)) {
			String sha256 = DigestUtils.sha256Hex(ins1);
			try (InputStream ins2 = new FileInputStream(file)) {
				HttpPost request = new WechatPayUploadHttpPost.Builder(uri).withImage(file.getName(), sha256, ins2)
						.build();
				CloseableHttpResponse response = httpClient.execute(request);
				try {
					int statusCode = response.getStatusLine().getStatusCode();
					if (statusCode == 200) { // 处理成功
						result = EntityUtils.toString(response.getEntity());
					} else if (statusCode == 204) { // 处理成功,无返回Body
						result = "{'code':204}";
					} else {
						result = EntityUtils.toString(response.getEntity());
					}
				} finally {
					response.close();
				}

			}
		}

		return result;
	}

	/**
	 * 下载图片
	 *
	 * @param media_url
	 *            图片路径
	 * @return
	 * @throws Exception
	 */
	public BufferedImage downLoadImg(String media_url, String filePath) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		HttpGet httpGet = new HttpGet(media_url);
		httpGet.setHeader("Accept", "application/json");

		CloseableHttpResponse response = httpNoSignPayClient.execute(httpGet);

		BufferedImage result = null;

		try {
			HttpEntity responseEntity = response.getEntity();
			InputStream content = responseEntity.getContent();
			result = ImageIO.read(content);
			if(filePath != null && filePath.length() >= 0){
				File file = new File(filePath);
				if(!file.exists()){
					file.createNewFile();
				}
				FileOutputStream fileOutputStream = new FileOutputStream(file);
				int bytesWritten = 0;
				int byteCount = 0;
				byte[] bytes = new byte[1024];
				while ((byteCount = content.read(bytes)) != -1)
				{
					fileOutputStream.write(bytes, bytesWritten, byteCount);
					bytesWritten += byteCount;
				}
				content.close();
				fileOutputStream.close();
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 发送请求
	 *
	 * @param url
	 *            发送地址
	 * @return
	 * @throws Exception
	 */
	public String doSendPostUrl(String url, String sendcontent) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpPost httpPost = new HttpPost(url);

		StringEntity entity = new StringEntity(sendcontent, "utf-8");
		entity.setContentType("application/json");
		httpPost.setEntity(entity);
		httpPost.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpPost);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	public String doSendPostUrl(String url, String sendcontent, String Wechatpay_Serial) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpPost httpPost = new HttpPost(url);

		StringEntity entity = new StringEntity(sendcontent, "utf-8");
		entity.setContentType("application/json");
		httpPost.setEntity(entity);
		httpPost.setHeader("Accept", "application/json");
		httpPost.addHeader("Wechatpay-Serial", Wechatpay_Serial);

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpPost);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 发送请求
	 *
	 * @param url
	 *            发送地址
	 * @return
	 * @throws Exception
	 */
	public String doSendGETUrl(String url) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		// 请求URL
		HttpGet httpGet = new HttpGet(url);
		httpGet.setHeader("Accept", "application/json");

		// 完成签名并执行请求
		CloseableHttpResponse response = httpClient.execute(httpGet);

		try {
			int statusCode = response.getStatusLine().getStatusCode();
			if (statusCode == 200) { // 处理成功
				result = EntityUtils.toString(response.getEntity());
			} else if (statusCode == 204) { // 处理成功,无返回Body
				result = "{'code':204}";
			} else {
				result = EntityUtils.toString(response.getEntity());
			}
		} finally {
			response.close();
		}

		return result;
	}

	/**
	 * 发送请求
	 *
	 * @param url
	 *            发送地址
	 * @return
	 * @throws Exception
	 */
	public String doSendPostImages(String url, String filepath) throws Exception {

		if (!isStep) {
			errorHint = "未成功启用Step";
			return null;
		}

		String result = null;

		File file = new File(filepath);
		URI uri = new URI(url);

		try (FileInputStream ins1 = new FileInputStream(file)) {
			String sha256 = DigestUtils.sha256Hex(ins1);
			try (InputStream ins2 = new FileInputStream(file)) {
				HttpPost request = new WechatPayUploadHttpPost.Builder(uri).withImage(file.getName(), sha256, ins2)
						.build();
				CloseableHttpResponse response = httpClient.execute(request);
				try {
					int statusCode = response.getStatusLine().getStatusCode();
					if (statusCode == 200) { // 处理成功
						result = EntityUtils.toString(response.getEntity());
					} else if (statusCode == 204) { // 处理成功,无返回Body
						result = "{'code':204}";
					} else {
						result = EntityUtils.toString(response.getEntity());
					}
				} catch (Exception e) {
					e.printStackTrace();
				} finally {
					response.close();
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return result;
	}

}

你就只用填写对应的参数后,调用上面的方法即可,是不是一下就简单了很多,哇,你们不知道,我当时憋了好久才把这个给憋通,-=- ,主要怪楼主自己没有认真看API文档
2023/07/25 新增下载图片方法

github 传送门:https://github.com/wintton/MxWxPayUtil.git
路径:src/com/mx/util/WeChatAPIV3.java

微信支付v3版的支付回调是基于异步通知机制进行的,需要在接收支付结果的服务器端编写Java代码来处理回调请求。以下是一个简单的示例代码: ```java import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse; import com.github.binarywang.wxpay.exception.WxPayException; import com.github.binarywang.wxpay.service.WxPayService; import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController @RequestMapping("/api/v1/pay") public class WechatPayCallbackController { private final WxPayService wxPayService; public WechatPayCallbackController() { // 初始化微信支付服务 wxPayService = new WxPayServiceImpl(); wxPayService.setKey("your-wxpay-api-key"); // 设置支付密钥 } @PostMapping("/callback") public String payCallback(@RequestBody String notifyData) { try { // 解析支付通知 wxPayService.parseNotifyResult(notifyData); // 处理支付成功逻辑,例如更新订单状态等 // 返回成功响应给微信支付平台 return WxPayNotifyResponse.success("处理成功"); } catch (WxPayException e) { // 处理支付失败逻辑,例如记录错误日志等 // 返回失败响应给微信支付平台 return WxPayNotifyResponse.fail(e.getMessage()); } } } ``` 上述代码是一个使用Spring Boot框架的控制器类,负责处理微信支付回调请求。在回调方法`payCallback`中,通过`wxPayService.parseNotifyResult`方法解析支付通知的XML数据,并在处理成功或失败后返回相应的结果。 需要注意的是,为了保证安全性,建议在实际开发中将`your-wxpay-api-key`替换为实际的支付密钥。 另外,此代码仅作为示例,实际情况可能需要结合具体的业务逻辑进行扩展和修改。
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵神翁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值