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

com.foxinmy.weixin4j.mp.payment.PayUtil Maven / Gradle / Ivy

package com.foxinmy.weixin4j.mp.payment;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.exception.PayException;
import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.HttpRequest;
import com.foxinmy.weixin4j.http.Response;
import com.foxinmy.weixin4j.model.Consts;
import com.foxinmy.weixin4j.model.WeixinMpAccount;
import com.foxinmy.weixin4j.mp.payment.v2.JsPayRequestV2;
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
import com.foxinmy.weixin4j.mp.payment.v2.PayPackageV2;
import com.foxinmy.weixin4j.mp.payment.v3.PayPackageV3;
import com.foxinmy.weixin4j.mp.payment.v3.PayRequestV3;
import com.foxinmy.weixin4j.mp.payment.v3.PrePay;
import com.foxinmy.weixin4j.mp.type.SignType;
import com.foxinmy.weixin4j.mp.type.TradeType;
import com.foxinmy.weixin4j.util.ConfigUtil;
import com.foxinmy.weixin4j.util.DateUtil;
import com.foxinmy.weixin4j.util.MapUtil;
import com.foxinmy.weixin4j.util.RandomUtil;
import com.foxinmy.weixin4j.xml.XmlStream;

/**
 * 支付工具类(JSAPI,NATIVE,MicroPay)
 * 
 * @className PayUtil
 * @author jy
 * @date 2014年10月28日
 * @since JDK 1.7
 * @see
 */
public class PayUtil {
	/**
	 * 生成JSAPI字符串
	 * 
	 * @param payPackage
	 *            订单信息
	 * @param WeixinMpAccount
	 *            商户信息
	 * @since V2 & V3
	 * @return 支付json串
	 * @throws PayException
	 */
	public static String createPayJsRequestJson(PayPackage payPackage,
			WeixinMpAccount weixinAccount) throws PayException {
		if (payPackage instanceof PayPackageV2) {
			return createPayJsRequestJsonV2((PayPackageV2) payPackage,
					weixinAccount);
		} else if (payPackage instanceof PayPackageV3) {
			return createPayJsRequestJsonV3((PayPackageV3) payPackage,
					weixinAccount);
		} else {
			throw new PayException("unknown pay");
		}
	}

	/**
	 * 生成V2.x版本JSAPI支付字符串
	 * 
	 * @param payPackage
	 *            订单信息
	 * @param weixinAccount
	 *            商户信息
	 * @return 支付json串
	 */
	public static String createPayJsRequestJsonV2(PayPackageV2 payPackage,
			WeixinMpAccount weixinAccount) {
		if (StringUtils.isBlank(payPackage.getPartner())) {
			payPackage.setPartner(weixinAccount.getPartnerId());
		}
		JsPayRequestV2 jsPayRequest = new JsPayRequestV2(weixinAccount,
				payPackage);
		jsPayRequest.setPaySign(paysignSha(jsPayRequest,
				weixinAccount.getPaySignKey()));
		jsPayRequest.setSignType(SignType.SHA1);
		return JSON.toJSONString(jsPayRequest);
	}

	/**
	 * 生成V2.x版本JSAPI支付字符串
	 * 
	 * @param body
	 *            支付详情
	 * @param orderNo
	 *            订单号
	 * @param orderFee
	 *            订单总额 按实际金额传入即可(元) 构造函数会转换为分
	 * @param ip
	 * @param weixinAccount
	 *            商户信息
	 * @return 支付json串
	 */
	public static String createPayJsRequestJsonV2(String body, String orderNo,
			double orderFee, String notify_url, String ip,
			WeixinMpAccount weixinAccount) {
		PayPackageV2 payPackage = new PayPackageV2(body, orderNo, orderFee,
				notify_url, ip);
		payPackage.setPartner(weixinAccount.getPartnerId());
		return createPayJsRequestJsonV2(payPackage, weixinAccount);
	}

	/**
	 * sha签名(一般用于V2.x支付接口)
	 * 
	 * @param obj
	 *            签名对象
	 * @return
	 */
	public static String paysignSha(Object obj) {
		return DigestUtils
				.sha1Hex(MapUtil.toJoinString(obj, false, true, null));
	}

	/**
	 * sha签名(一般用于V2.x支付接口)
	 * 
	 * @param obj
	 *            签名对象
	 * @param paySignKey
	 *            支付API的密钥请注意排序放进去的是put("appKey",
	 *            paySignKey)
	 * @return
	 */
	public static String paysignSha(Object obj, String paySignKey) {
		Map extra = new HashMap();
		extra.put("appKey", paySignKey);
		return DigestUtils.sha1Hex(MapUtil
				.toJoinString(obj, false, true, extra));
	}

	/**
	 * md5签名(一般用于V3.x支付接口)
	 * 
	 * @param obj
	 *            签名对象
	 * @param paySignKey
	 *            支付API的密钥
	 * @return
	 */
	public static String paysignMd5(Object obj, String paySignKey) {
		StringBuilder sb = new StringBuilder();
		// a--->string1
		sb.append(MapUtil.toJoinString(obj, false, false, null));
		// b--->
		// 在 string1 最后拼接上 key=paternerKey 得到 stringSignTemp 字符串,并 对
		// stringSignTemp 进行 md5 运算
		// 再将得到的 字符串所有字符转换为大写 ,得到 sign 值 signValue。
		sb.append("&key=").append(paySignKey);
		return DigestUtils.md5Hex(sb.toString()).toUpperCase();
	}

	/**
	 * 生成V3.x版本JSAPI支付字符串
	 * 
	 * @param openId
	 *            用户ID
	 * @param body
	 *            订单描述
	 * @param orderNo
	 *            订单号
	 * @param orderFee
	 *            订单总额 按实际金额传入即可(元) 构造函数会转换为分
	 * @param notifyUrl
	 *            支付通知地址
	 * @param ip
	 *            ip地址
	 * @param weixinAccount
	 *            商户信息
	 * @return 支付json串
	 * @throws PayException
	 */
	public static String createPayJsRequestJsonV3(String openId, String body,
			String orderNo, double orderFee, String notifyUrl, String ip,
			WeixinMpAccount weixinAccount) throws PayException {
		PayPackageV3 payPackage = new PayPackageV3(weixinAccount, openId, body,
				orderNo, orderFee, ip, TradeType.JSAPI);
		payPackage.setNotifyUrl(notifyUrl);
		return createPayJsRequestJsonV3(payPackage, weixinAccount);
	}

	/**
	 * 生成V3.x版本JSAPI支付字符串
	 * 
	 * @param payPackage
	 *            订单信息
	 * @param weixinAccount
	 *            商户信息
	 * @return 支付json串
	 * @throws PayException
	 */
	public static String createPayJsRequestJsonV3(PayPackageV3 payPackage,
			WeixinMpAccount weixinAccount) throws PayException {
		String paySignKey = weixinAccount.getPaySignKey();
		payPackage.setSign(paysignMd5(payPackage, paySignKey));
		PrePay prePay = createPrePay(payPackage, paySignKey);
		PayRequestV3 jsPayRequest = new PayRequestV3(prePay);
		jsPayRequest.setSignType(SignType.MD5);
		jsPayRequest.setPaySign(paysignMd5(jsPayRequest, paySignKey));
		return JSON.toJSONString(jsPayRequest);
	}

	/**
	 * 统一下单接口
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI * 、APP等不同场景生成交易串调起支付。 * * @param payPackage * 包含订单信息的对象 * @param paySignKey * 如果sign为空 则拿paysignkey进行签名 * @see com.foxinmy.weixin4j.mp.payment.v3.PayPackageV3 * @see com.foxinmy.weixin4j.mp.payment.v3.PrePay * @see 统一下单接口 * @return 预支付对象 */ public static PrePay createPrePay(PayPackageV3 payPackage, String paySignKey) throws PayException { if (StringUtils.isBlank(payPackage.getSign())) { payPackage.setSign(paysignMd5(payPackage, paySignKey)); } String payJsRequestXml = XmlStream.to(payPackage).replaceAll("__", "_"); HttpRequest request = new HttpRequest(); try { Response response = request.post(Consts.UNIFIEDORDER, payJsRequestXml); PrePay prePay = response.getAsObject(new TypeReference() { }); if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) { throw new PayException(prePay.getReturnMsg(), prePay.getReturnCode()); } if (!prePay.getResultCode().equalsIgnoreCase(Consts.SUCCESS)) { throw new PayException(prePay.getResultCode(), prePay.getErrCodeDes()); } return prePay; } catch (WeixinException e) { throw new PayException(e.getErrorCode(), e.getErrorMsg()); } } /** *

* 生成编辑地址请求 *

* * err_msg edit_address:ok获取编辑收货地址成功
edit_address:fail获取编辑收货地址失败
* userName 收货人姓名
telNumber 收货人电话
addressPostalCode 邮编
* proviceFirstStageName 国标收货地址第一级地址
addressCitySecondStageName * 国标收货地址第二级地址
addressCountiesThirdStageName 国标收货地址第三级地址
* addressDetailInfo 详细收货地址信息
nationalCode 收货地址国家码
* * @param appId * 公众号的ID * @param url * 当前访问页的URL * @param accessToken * snsapi_base授权时产生的token * @return */ public static String createAddressRequestJson(String appId, String url, String accessToken) { Map map = new HashMap(); map.put("appId", appId); map.put("timeStamp", DateUtil.timestamp2string()); map.put("nonceStr", RandomUtil.generateString(16)); map.put("url", url); map.put("accessToken", accessToken); String sign = paysignSha(map); map.remove("url"); map.remove("accessToken"); map.put("scope", "jsapi_address"); map.put("signType", SignType.SHA1.name().toLowerCase()); map.put("addrSign", sign); return JSON.toJSONString(map); } /** * 创建V2.x NativePay支付链接 * * @param weixinAccount * 商户信息 * @param productId * 与订单ID等价 * @return */ public static String createNativePayRequestURLV2( WeixinMpAccount weixinAccount, String productId) { Map map = new HashMap(); String timestamp = DateUtil.timestamp2string(); String noncestr = RandomUtil.generateString(16); map.put("appid", weixinAccount.getId()); map.put("timestamp", timestamp); map.put("noncestr", noncestr); map.put("productid", productId); map.put("appkey", weixinAccount.getPaySignKey()); String sign = paysignSha(map); return String.format(Consts.NATIVEURLV2, sign, weixinAccount.getId(), productId, timestamp, noncestr); } /** * 创建V3.x NativePay支付(扫码支付)链接 * * @param weixinAccount * 支付配置信息 * @param productId * 与订单ID等价 * @return * @see 扫码支付 */ public static String createNativePayRequestURLV3( WeixinMpAccount weixinAccount, String productId) { Map map = new HashMap(); String timestamp = DateUtil.timestamp2string(); String noncestr = RandomUtil.generateString(16); map.put("appid", weixinAccount.getId()); map.put("mch_id", weixinAccount.getMchId()); map.put("time_stamp", timestamp); map.put("nonce_str", noncestr); map.put("product_id", productId); String sign = paysignMd5(map, weixinAccount.getPaySignKey()); return String.format(Consts.NATIVEURLV3, sign, weixinAccount.getId(), weixinAccount.getMchId(), productId, timestamp, noncestr); } /** * 创建V2.x NATIVE回调时的响应字符串 * * @param weixinAccount * 商户信息 * @param payPackage * 订单信息 * @return */ public static String createNativePayResponseV2( WeixinMpAccount weixinAccount, PayPackageV2 payPackage) { NativePayResponseV2 payRequest = new NativePayResponseV2(weixinAccount, payPackage); Map map = new HashMap(); String timestamp = DateUtil.timestamp2string(); String noncestr = RandomUtil.generateString(16); map.put("appid", weixinAccount.getId()); map.put("appkey", weixinAccount.getPaySignKey()); map.put("timestamp", timestamp); map.put("noncestr", noncestr); map.put("package", payRequest.getPackageInfo()); map.put("retcode", payRequest.getRetCode()); map.put("reterrmsg", payRequest.getRetMsg()); payRequest.setPaySign(paysignSha(map)); return XmlStream.to(payRequest); } /** * 提交被扫支付 * * @param authCode * 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息 * @param body * 商品描述 * @param attach * 附加数据 * @param orderNo * 商户内部唯一订单号 * @param orderFee * 商品总额 单位元 * @param ip * 订单生成的机器 IP * @param weixinAccount * 商户信息 * @return 支付的订单信息 * @see {@link com.foxinmy.weixin4j.mp.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinMpAccount)} * @throws WeixinException */ public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay( String authCode, String body, String attach, String orderNo, double orderFee, String ip, WeixinMpAccount weixinAccount) throws WeixinException { MicroPayPackage payPackage = new MicroPayPackage(weixinAccount, body, attach, orderNo, orderFee, ip, authCode); return createMicroPay(payPackage, weixinAccount); } /** * 提交被扫支付:收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付. * * @param payPackage * 订单信息 * @param weixinAccount * 商户信息 * @return 支付的订单信息 * @throws WeixinException * @see com.foxinmy.weixin4j.mp.payment.v3.Order * @see 提交被扫支付API */ public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay( MicroPayPackage payPackage, WeixinMpAccount weixinAccount) throws WeixinException { String sign = paysignMd5(payPackage, weixinAccount.getPaySignKey()); payPackage.setSign(sign); String para = XmlStream.to(payPackage).replaceAll("__", "_"); HttpRequest request = new HttpRequest(); Response response = request.post(Consts.MICROPAYURL, para); return response .getAsObject(new TypeReference() { }); } private static String JSAPIV2() { WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount(); return createPayJsRequestJsonV2("支付测试", "JSAPI01", 0.01d, "127.0.0.0", "http://127.0.0.1/jsapi/notify", weixinAccount); } private static String NATIVEV2() { WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount(); return createNativePayRequestURLV2(weixinAccount, "P1"); } private static String JSAPIV3() throws PayException { WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount(); return createPayJsRequestJsonV3("oyFLst1bqtuTcxK-ojF8hOGtLQao", "支付测试", "JSAPI01", 0.01d, "http://127.0.0.1/jsapi/notify", "127.0.0.0", weixinAccount); } private static String NATIVEV3() { WeixinMpAccount weixinAccount = ConfigUtil.getWeixinMpAccount(); return createNativePayRequestURLV3(weixinAccount, "P1"); } public static void main(String[] args) throws PayException { // V2版本下的JS支付 System.out.println(JSAPIV2()); // V2版本下的原生支付 System.out.println(NATIVEV2()); // V3版本下的JS支付 System.out.println(JSAPIV3()); // V3版本下的原生支付 System.out.println(NATIVEV3()); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy