微信MP端、APP端、PC端,支付宝APP端、PC端请求支付及回调集成处理分享

/**
 * 请求付款相关工具
 * 
 * @author Luyao
 *
 */
public class PaymentKit {

	/**
	 * 请求微信付款
	 * 
	 * @param orderNo
	 * @param productName
	 * @param amount
	 * @param platform
	 * @param openId
	 * @return
	 */
	public static Ret requestWechatPay(String orderNo, String productName, BigDecimal amount, String notifyUrl,
			int platform, String... openId) {
		Prop prop = PropKit.use("wechat.txt");
		// 应用id
		String appId = prop.get("mp_appid");
		String tradeType = prop.get("mp_trade_type");
		if (platform == PlatformEnum.APP.getCode()) {
			appId = prop.get("pay_appid");
			tradeType = prop.get("app_trade_type");
		} else if (platform == PlatformEnum.PC.getCode()) {
			appId = prop.get("pay_appid");
			tradeType = prop.get("pc_trade_type");
		}
		// 封装请求参数
		Map<String, String> params = new HashMap<>();
		params.put("appid", appId);
		// 商户id
		params.put("mch_id", prop.get("mchid"));
		// 随机数
		params.put("nonce_str", StrKit.getRandomUUID());
		// 商品信息
		params.put("body", productName);
		// 订单号
		params.put("out_trade_no", orderNo);
		// 订单金额
		params.put("total_fee", String.valueOf(amount.multiply(new BigDecimal("100")).intValue()));
		// 回调地址
		params.put("notify_url", PropKit.use("app_config.txt").get("domain_name") + notifyUrl);
		// 支付类型
		params.put("trade_type", tradeType);
		// 支付超时时间
		Calendar expiredTime = Calendar.getInstance();
		expiredTime.add(Calendar.MINUTE, 5);
		params.put("time_expire", DateKit.toStr(expiredTime.getTime(), "yyyyMMddHHmmss"));
		// 如果是小程序支付,还需传入openId
		if (platform == PlatformEnum.MP.getCode()) {
			if (openId.length == 0 || StrKit.isBlank(openId[0]))
				return Ret.fail("msg", ErrorMsg.PARA_EMPTY);
			params.put("openid", openId[0]);
		}
		// MD5签名
		String signKey = prop.get("key");
		params.put("sign", StringKit.genMd5Sign(params, signKey));
		// 发送付款请求并返回结果
		String result = HttpKit.post(prop.get("pay_url"), StringKit.mapToXml(params));
		if (StrKit.isBlank(result))
			return Ret.fail("msg", ErrorMsg.REQUEST_FAIL);
		Map<String, String> response = StringKit.xmlToMap(result);
		// 请求成功需返回状态和返回结果均为成功
		if (response == null || !response.get("return_code").equals(UserPaymetRecord.WechatResult.CODE)
				|| !response.get("result_code").equals(UserPaymetRecord.WechatResult.CODE)) {
			LogKit.error("请求微信支付失败:" + response.get("err_code_des"));
			return Ret.fail("msg", ErrorMsg.REQUEST_FAIL);
		}
		// 根据不同平台返回不同数据
		return packageWechatPayData(response, platform, signKey);
	}

	/**
	 * 封装微信支付需要的参数
	 * 
	 * @param response
	 * @param platform
	 * @param signKey
	 * @return
	 */
	private static Ret packageWechatPayData(Map<String, String> response, int platform, String signKey) {
		// 小程序和app支付,都需封装map
		Map<String, String> data = new HashMap<>();
		if (platform == PlatformEnum.MP.getCode()) {
			// 小程序应用id
			data.put("appId", response.get("appid"));
			// 时间戳
			data.put("timeStamp", new Date().getTime() + "");
			// 随机字符串
			data.put("nonceStr", StrKit.getRandomUUID());
			// 数据包
			data.put("package", "prepay_id=" + response.get("prepay_id"));
			// 签名方式
			data.put("signType", "MD5");
			// 数据签名
			data.put("paySign", StringKit.genMd5Sign(data, signKey));
		} else if (platform == PlatformEnum.APP.getCode()) {
			// APP应用id
			data.put("appid", response.get("appid"));
			// 商户id
			data.put("partnerid", response.get("mch_id"));
			// 预支付交易会话id
			data.put("prepayid", response.get("prepay_id"));
			// 数据包
			data.put("package", "Sign=WXPay");
			// 随机字符串
			data.put("noncestr", StrKit.getRandomUUID());
			// 时间戳
			data.put("timestamp", new Date().getTime() + "");
			// 数据签名
			data.put("sign", StringKit.genMd5Sign(data, signKey));
		} else {
			// PC端二维码支付,获取要生成二维码的付款链接
			String codeUrl = response.get("code_url");
			if (StrKit.isBlank(codeUrl))
				return Ret.fail("msg", ErrorMsg.REQUEST_FAIL);
			// 生成Base64形式的包含微信支付logo的二维码图片并返回
			// TODO
			return Ret.ok("data", codeUrl);
		}
		return Ret.ok("data", data);
	}

	/**
	 * 微信支付回调处理
	 * 
	 * @param xmlData
	 * @return
	 */
	public static Ret wechatCallback(String xmlData) {
		Map<String, String> xmlMap = new HashMap<>();
		xmlMap.put("return_code", WechatResult.CODE);
		xmlMap.put("return_msg", WechatResult.MSG);
		String result = StringKit.mapToXml(xmlMap);
		// 判断是否为空
		if (StrKit.notBlank(xmlData)) {
			// 校验签名
			Map<String, String> data = StringKit.xmlToMap(xmlData);
			String signKey = PropKit.use("wechat.txt").get("key");
			if (StringKit.verifyMd5Sign(data, signKey)) {
				// 判断支付状态
				if (WechatResult.CODE.equals(data.get("result_code"))) {
					// 封装返回的数据
					PaymentResult paymentResult = new PaymentResult();
					paymentResult.setOrderNo(data.get("out_trade_no"));
					paymentResult.setPlatfromOrderNo(data.get("transaction_id"));
					paymentResult.setAmount(new BigDecimal(data.get("total_fee")).divide(new BigDecimal("100")));
					// 转换日期格式:yyyyMMddHHmmss to -> yyyy-MM-dd HH:mm:ss
					String date = data.get("time_end");
					String reg = "(\\d{4})(\\d{2})(\\d{2})(\\d{2})(\\d{2})(\\d{2})";
					date = date.replaceAll(reg, "$1-$2-$3 $4:$5:$6");
					paymentResult.setSuccessTime(DateKit.toDate(date));
					// 将通知结果和返回参数一起封装
					Map<String, Object> response = new HashMap<>();
					response.put("xml", result);
					response.put("data", paymentResult);
					return Ret.ok("map", response);
				}
			}
		}
		return Ret.fail("xml", result);
	}

	/**
	 * 请求支付宝付款
	 * 
	 * @param orderNo
	 * @param productName
	 * @param amount
	 * @param notifyUrl
	 * @param platform
	 * @return
	 */
	public static Ret requestAlipay(String orderNo, String productName, BigDecimal amount, String notifyUrl,
			int platform) {
		Prop prop = PropKit.use("alipay.txt");
		if (platform == PlatformEnum.APP.getCode()) {
			AlipayClient alipayClient = new DefaultAlipayClient(prop.get("open_api_domain"), prop.get("appid"),
					prop.get("private_key"), "JSON", Const.CHARSET, prop.get("alipay_public_key"),
					prop.get("sign_type"));
			AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
			AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
			model.setBody(productName);
			model.setSubject(productName);
			model.setOutTradeNo(orderNo);
			model.setTimeoutExpress("5m");
			model.setTotalAmount(amount.toString());
			model.setProductCode("QUICK_MSECURITY_PAY");
			request.setBizModel(model);
			request.setNotifyUrl(PropKit.use("app_config.txt").get("domain_name") + notifyUrl);
			try {
				return Ret.ok("data", alipayClient.sdkExecute(request).getBody());
			} catch (AlipayApiException e) {
				e.printStackTrace();
				return Ret.fail("msg", ErrorMsg.REQUEST_FAIL);
			}
		} else if (platform == PlatformEnum.PC.getCode()) {
			// 创建扫码支付请求builder,设置请求参数
			AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
					.setSubject(productName).setTotalAmount(amount.toString()).setOutTradeNo(orderNo)
					.setTimeoutExpress("5m").setStoreId("001").setNotifyUrl(prop.get("domain_name") + notifyUrl);
			Configs.init("alipay.txt");
			AlipayTradeService tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();
			AlipayTradePrecreateResponse response = tradeService.tradePrecreate(builder).getResponse();
			if (response.isSuccess()) {
				// 生成Base64形式的包含支付宝logo的二维码图片并返回
				// TODO
				return Ret.ok("data", response.getQrCode());
			}
			return Ret.fail("msg", ErrorMsg.REQUEST_FAIL);
		} else {
			return Ret.fail("msg", ErrorMsg.PARA_ERROR);
		}
	}

	/**
	 * 支付宝回调处理
	 * 
	 * @param params
	 * @return
	 */
	public static Ret alipayCallback(Map<String, String[]> params) {
		// 解析参数
		Map<String, String> data = new HashMap<>();
		for (Iterator<String> iterator = params.keySet().iterator(); iterator.hasNext();) {
			String name = iterator.next();
			String[] values = params.get(name);
			StringBuilder value = new StringBuilder();
			for (String param : values)
				value.append(param);
			data.put(name, value.toString());
		}
		String returnResult = AlipayResult.SUCCESS;
		// 判断是否为空
		if (data.size() > 0) {
			// 校验签名
			boolean result = false;
			try {
				result = AlipaySignature.rsaCheckV1(data, "your AlipayPublicKey", Const.CHARSET,
						"your SignType");
			} catch (AlipayApiException e) {
				e.printStackTrace();
				return Ret.fail("result", returnResult);
			}
			if (result) {
				// 判断支付状态
				if (AlipayResult.TRADE_STATUS_SUCCESS.equals(data.get("trade_status"))) {
					// 封装返回的数据
					PaymentResult paymentResult = new PaymentResult();
					paymentResult.setOrderNo(data.get("out_trade_no"));
					paymentResult.setPlatfromOrderNo(data.get("trade_no"));
					paymentResult.setAmount(new BigDecimal(data.get("total_amount")));
					paymentResult.setSuccessTime(DateKit.toDate(data.get("gmt_payment")));
					// 将通知结果和返回参数一起封装
					Map<String, Object> response = new HashMap<>();
					response.put("result", returnResult);
					response.put("data", paymentResult);
					return Ret.ok("map", response);
				}
			}
		}
		return Ret.fail("result", returnResult);
	}
}


评论区

JFinal

2018-12-16 17:12

这是个大招啊,这么少的代码搞定两个平台的支付,收藏加点赞,我自己还差一个阿里的支付呢,感谢分享

简单简单

2018-12-16 20:56

支持

简单简单

2018-12-21 13:04

Missing artifact com.alipay:alipay-trade-sdk:jar:alipay-trade-sdk-20161215.jar

NOKIA

2019-05-20 15:22

坚挺,牛X

爱在当时

2021-10-24 23:28

缺少的工具类有吗

热门分享

扫码入社