All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mizhousoft.weixin.payment.service.impl.WxPaymentServiceImpl Maven / Gradle / Ivy

The newest version!
package com.mizhousoft.weixin.payment.service.impl;

import java.time.Instant;

import org.apache.commons.lang3.StringUtils;

import com.mizhousoft.commons.crypto.generator.RandomGenerator;
import com.mizhousoft.commons.json.JSONException;
import com.mizhousoft.commons.json.JSONUtils;
import com.mizhousoft.weixin.cipher.CipherService;
import com.mizhousoft.weixin.common.WXException;
import com.mizhousoft.weixin.payment.SignatureHeader;
import com.mizhousoft.weixin.payment.WxPayConfig;
import com.mizhousoft.weixin.payment.request.WxPayOrderCreateRequest;
import com.mizhousoft.weixin.payment.request.WxPayRefundRequest;
import com.mizhousoft.weixin.payment.response.OriginNotifyResponse;
import com.mizhousoft.weixin.payment.response.WxPayOrderCreateResponse;
import com.mizhousoft.weixin.payment.result.WxPayOrderCreateResult;
import com.mizhousoft.weixin.payment.result.WxPayOrderQueryResult;
import com.mizhousoft.weixin.payment.result.WxPayRefundNotifyResult;
import com.mizhousoft.weixin.payment.result.WxPayRefundResult;
import com.mizhousoft.weixin.payment.service.WxPayConfigService;
import com.mizhousoft.weixin.payment.service.WxPayHttpClient;
import com.mizhousoft.weixin.payment.service.WxPaymentService;

import kong.unirest.core.HttpResponse;

/**
 * 支付服务
 *
 */
public class WxPaymentServiceImpl implements WxPaymentService
{
	private WxPayConfigService configService;

	private WxPayHttpClient httpClient;

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayOrderCreateResult createAppOrder(WxPayOrderCreateRequest request) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(request.getMchId());

		String canonicalUrl = "/v3/pay/transactions/app";

		WxPayOrderCreateResponse response = createUnifiedOrder(payConfig, canonicalUrl, request);

		String prepayId = response.getPrepayId();

		long timestamp = Instant.now().getEpochSecond();
		String nonceStr = RandomGenerator.genHexString(16, false);

		String message = request.getAppId() + "\n" + timestamp + "\n" + nonceStr + "\n" + prepayId + "\n";
		String sign = payConfig.getCipherService().sign(message);

		WxPayOrderCreateResult result = new WxPayOrderCreateResult();
		result.setAppId(request.getAppId());
		result.setPartnerId(payConfig.getMchId());
		result.setPrepayId(prepayId);
		result.setPackageValue("Sign=WXPay");
		result.setNonceStr(nonceStr);
		result.setTimeStamp(String.valueOf(timestamp));
		result.setSign(sign);

		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayOrderCreateResult createJSAPIOrder(WxPayOrderCreateRequest request) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(request.getMchId());

		String canonicalUrl = "/v3/pay/transactions/jsapi";

		WxPayOrderCreateResponse response = createUnifiedOrder(payConfig, canonicalUrl, request);

		String prepayId = response.getPrepayId();
		String packageValue = "prepay_id=" + prepayId;

		long timestamp = Instant.now().getEpochSecond();
		String nonceStr = RandomGenerator.genHexString(16, false);

		String message = request.getAppId() + "\n" + timestamp + "\n" + nonceStr + "\n" + packageValue + "\n";
		String sign = payConfig.getCipherService().sign(message);

		WxPayOrderCreateResult result = new WxPayOrderCreateResult();
		result.setAppId(request.getAppId());
		result.setPackageValue(packageValue);
		result.setNonceStr(nonceStr);
		result.setTimeStamp(String.valueOf(timestamp));
		result.setSign(sign);
		result.setSignType("RSA");

		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String createH5Order(WxPayOrderCreateRequest request) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(request.getMchId());

		String canonicalUrl = "/v3/pay/transactions/h5";

		WxPayOrderCreateResponse response = createUnifiedOrder(payConfig, canonicalUrl, request);

		return response.getH5Url();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String createNativeOrder(WxPayOrderCreateRequest request) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(request.getMchId());

		String canonicalUrl = "/v3/pay/transactions/native";

		WxPayOrderCreateResponse response = createUnifiedOrder(payConfig, canonicalUrl, request);

		return response.getCodeUrl();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayOrderQueryResult queryOrderByTransactionId(String mchId, String transactionId) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(mchId);

		String canonicalUrl = String.format("/v3/pay/transactions/id/%s?mchid=%s", transactionId, mchId);

		HttpResponse httpResp = httpClient.get(canonicalUrl, false, payConfig);

		try
		{
			WxPayOrderQueryResult response = JSONUtils.parse(httpResp.getBody(), WxPayOrderQueryResult.class);

			return response;
		}
		catch (JSONException e)
		{
			throw new WXException("JSON to object failed.", e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayOrderQueryResult queryOrderByOutTradeNo(String mchId, String outTradeNo) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(mchId);

		String canonicalUrl = String.format("/v3/pay/transactions/out-trade-no/%s?mchid=%s", outTradeNo, mchId);

		HttpResponse httpResp = httpClient.get(canonicalUrl, false, payConfig);

		try
		{
			WxPayOrderQueryResult response = JSONUtils.parse(httpResp.getBody(), WxPayOrderQueryResult.class);

			return response;
		}
		catch (JSONException e)
		{
			throw new WXException("JSON to object failed.", e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayOrderQueryResult parsePayOrderNotifyResult(String mchId, String notifyData, SignatureHeader header) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(mchId);
		CipherService cipherService = payConfig.getCipherService();

		String beforeSign = String.format("%s\n%s\n%s\n", header.getTimeStamp(), header.getNonce(), notifyData);
		if (!cipherService.verify(header.getSerialNumber(), beforeSign, header.getSignature()))
		{
			throw new WXException("Request invalid.");
		}

		try
		{
			OriginNotifyResponse response = JSONUtils.parse(notifyData, OriginNotifyResponse.class);
			OriginNotifyResponse.Resource resource = response.getResource();
			String cipherText = resource.getCiphertext();
			String associatedData = resource.getAssociatedData();
			String nonce = resource.getNonce();

			String result = cipherService.decryptResult(associatedData, nonce, cipherText);

			WxPayOrderQueryResult queryResult = JSONUtils.parse(result, WxPayOrderQueryResult.class);

			return queryResult;
		}
		catch (JSONException e)
		{
			throw new WXException("JSON to object failed.", e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayRefundResult refund(String mchId, WxPayRefundRequest request) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(mchId);

		if (StringUtils.isBlank(request.getNotifyUrl()))
		{
			request.setNotifyUrl(payConfig.getRefundNotifyUrl());
		}

		String canonicalUrl = "/v3/refund/domestic/refunds";

		try
		{
			String body = JSONUtils.toJSONString(request);

			HttpResponse httpResp = httpClient.post(body, canonicalUrl, false, payConfig);

			WxPayRefundResult result = JSONUtils.parse(httpResp.getBody(), WxPayRefundResult.class);

			return result;
		}
		catch (JSONException e)
		{
			throw new WXException("JSON to object failed.", e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayRefundResult refundQuery(String mchId, String outRefundNo) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(mchId);

		String canonicalUrl = String.format("/v3/refund/domestic/refunds/%s", outRefundNo);

		HttpResponse httpResp = httpClient.get(canonicalUrl, false, payConfig);

		try
		{
			WxPayRefundResult response = JSONUtils.parse(httpResp.getBody(), WxPayRefundResult.class);

			return response;
		}
		catch (JSONException e)
		{
			throw new WXException("JSON to object failed.", e);
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public WxPayRefundNotifyResult parseRefundNotifyResult(String mchId, String notifyData, SignatureHeader header) throws WXException
	{
		WxPayConfig payConfig = configService.getByMchId(mchId);
		CipherService cipherService = payConfig.getCipherService();

		String beforeSign = String.format("%s\n%s\n%s\n", header.getTimeStamp(), header.getNonce(), notifyData);
		if (!cipherService.verify(header.getSerialNumber(), beforeSign, header.getSignature()))
		{
			throw new WXException("Request invalid.");
		}

		try
		{
			OriginNotifyResponse response = JSONUtils.parse(notifyData, OriginNotifyResponse.class);
			OriginNotifyResponse.Resource resource = response.getResource();
			String cipherText = resource.getCiphertext();
			String associatedData = resource.getAssociatedData();
			String nonce = resource.getNonce();

			String result = cipherService.decryptResult(associatedData, nonce, cipherText);

			WxPayRefundNotifyResult refundResult = JSONUtils.parse(result, WxPayRefundNotifyResult.class);

			return refundResult;
		}
		catch (JSONException e)
		{
			throw new WXException("JSON to object failed.", e);
		}
	}

	private WxPayOrderCreateResponse createUnifiedOrder(WxPayConfig payConfig, String canonicalUrl, WxPayOrderCreateRequest request)
	        throws WXException
	{
		if (StringUtils.isBlank(request.getMchId()))
		{
			request.setMchId(payConfig.getMchId());
		}

		if (StringUtils.isBlank(request.getNotifyUrl()))
		{
			request.setNotifyUrl(payConfig.getPayNotifyUrl());
		}

		try
		{
			String body = JSONUtils.toJSONString(request);

			HttpResponse httpResp = httpClient.post(body, canonicalUrl, false, payConfig);

			WxPayOrderCreateResponse response = JSONUtils.parse(httpResp.getBody(), WxPayOrderCreateResponse.class);

			return response;
		}
		catch (JSONException e)
		{
			throw new WXException("JSON to object failed.", e);
		}
	}

	/**
	 * 设置configService
	 * 
	 * @param configService
	 */
	public void setConfigService(WxPayConfigService configService)
	{
		this.configService = configService;
	}

	/**
	 * 设置httpClient
	 * 
	 * @param httpClient
	 */
	public void setHttpClient(WxPayHttpClient httpClient)
	{
		this.httpClient = httpClient;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy