删除PayUtil类,接口转移到PayApi类 #16
This commit is contained in:
parent
b21d61144a
commit
0a1cad7341
@ -553,3 +553,8 @@
|
||||
+ weixin4j-mp:新增个性化菜单接口
|
||||
|
||||
+ weixin4j-mp:WeixinProxy.getCustomRecord 参数变更为 Date startTime, Date endTime, Pageable pageable
|
||||
|
||||
|
||||
* 2015-12-19
|
||||
|
||||
+ weixin4j-base:删除PayUtil类,接口转移到PayApi类
|
||||
|
||||
@ -91,4 +91,8 @@
|
||||
|
||||
+【重要】修改PayUtil中的createPayJsRequest方法的返回值为MchPayRequest,便于二次发起支付。
|
||||
|
||||
+【重要】添加MchPayRequest的构造函数,便于二次发起支付。
|
||||
+【重要】添加MchPayRequest的构造函数,便于二次发起支付。
|
||||
|
||||
* 2015-12-19
|
||||
|
||||
+ 删除PayUtil类,接口转移到PayApi类
|
||||
@ -14,13 +14,13 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.PayURLConsts;
|
||||
import com.foxinmy.weixin4j.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.payment.mch.MPPayment;
|
||||
import com.foxinmy.weixin4j.payment.mch.MPPaymentRecord;
|
||||
import com.foxinmy.weixin4j.payment.mch.MPPaymentResult;
|
||||
import com.foxinmy.weixin4j.payment.mch.Redpacket;
|
||||
import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
|
||||
import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
@ -65,7 +65,7 @@ public class CashApi {
|
||||
obj.put("mch_id", weixinAccount.getMchId());
|
||||
obj.put("sub_mch_id", weixinAccount.getSubMchId());
|
||||
obj.put("wxappid", weixinAccount.getId());
|
||||
String sign = PayUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
|
||||
obj.put("sign", sign);
|
||||
String param = XmlStream.map2xml(obj);
|
||||
WeixinResponse response = null;
|
||||
@ -108,7 +108,7 @@ public class CashApi {
|
||||
para.put("bill_type", "MCHT");
|
||||
para.put("appid", weixinAccount.getId());
|
||||
para.put("mch_billno", outTradeNo);
|
||||
String sign = PayUtil.paysignMd5(para, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(para, weixinAccount.getPaySignKey());
|
||||
para.put("sign", sign);
|
||||
String param = XmlStream.map2xml(para);
|
||||
WeixinResponse response = null;
|
||||
@ -152,7 +152,7 @@ public class CashApi {
|
||||
obj.put("sub_mch_id", weixinAccount.getSubMchId());
|
||||
obj.put("mch_appid", weixinAccount.getId());
|
||||
obj.put("device_info", weixinAccount.getDeviceInfo());
|
||||
String sign = PayUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
|
||||
obj.put("sign", sign);
|
||||
String param = XmlStream.map2xml(obj);
|
||||
WeixinResponse response = null;
|
||||
@ -198,7 +198,7 @@ public class CashApi {
|
||||
obj.put("mch_id", weixinAccount.getMchId());
|
||||
obj.put("appid", weixinAccount.getId());
|
||||
obj.put("partner_trade_no", outTradeNo);
|
||||
String sign = PayUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(obj, weixinAccount.getPaySignKey());
|
||||
obj.put("sign", sign);
|
||||
String param = XmlStream.map2xml(obj);
|
||||
WeixinResponse response = null;
|
||||
|
||||
@ -12,10 +12,10 @@ import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.PayURLConsts;
|
||||
import com.foxinmy.weixin4j.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.payment.coupon.CouponDetail;
|
||||
import com.foxinmy.weixin4j.payment.coupon.CouponResult;
|
||||
import com.foxinmy.weixin4j.payment.coupon.CouponStock;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
@ -75,7 +75,7 @@ public class CouponApi {
|
||||
map.put("op_user_id", opUserId);
|
||||
map.put("version", "1.0");
|
||||
map.put("type", "XML");
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = null;
|
||||
@ -112,7 +112,7 @@ public class CouponApi {
|
||||
throws WeixinException {
|
||||
Map<String, String> map = baseMap();
|
||||
map.put("coupon_stock_id", couponStockId);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -136,7 +136,7 @@ public class CouponApi {
|
||||
throws WeixinException {
|
||||
Map<String, String> map = baseMap();
|
||||
map.put("coupon_id", couponId);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
|
||||
@ -18,24 +18,31 @@ import java.util.Map;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.MicroPayPackage;
|
||||
import com.foxinmy.weixin4j.payment.PayURLConsts;
|
||||
import com.foxinmy.weixin4j.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.payment.mch.ApiResult;
|
||||
import com.foxinmy.weixin4j.payment.mch.AuthCodeOpenIdResult;
|
||||
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
|
||||
import com.foxinmy.weixin4j.payment.mch.MchPayRequest;
|
||||
import com.foxinmy.weixin4j.payment.mch.Order;
|
||||
import com.foxinmy.weixin4j.payment.mch.PrePay;
|
||||
import com.foxinmy.weixin4j.payment.mch.RefundRecord;
|
||||
import com.foxinmy.weixin4j.payment.mch.RefundResult;
|
||||
import com.foxinmy.weixin4j.type.BillType;
|
||||
import com.foxinmy.weixin4j.type.CurrencyType;
|
||||
import com.foxinmy.weixin4j.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.type.IdType;
|
||||
import com.foxinmy.weixin4j.type.SignType;
|
||||
import com.foxinmy.weixin4j.type.TradeType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||
@ -55,7 +62,6 @@ import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
public class Pay3Api {
|
||||
|
||||
private final WeixinRequestExecutor weixinExecutor;
|
||||
|
||||
private final WeixinPayAccount weixinAccount;
|
||||
|
||||
public Pay3Api(WeixinPayAccount weixinAccount) {
|
||||
@ -63,6 +69,276 @@ public class Pay3Api {
|
||||
this.weixinExecutor = new WeixinRequestExecutor();
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一下单接口</br>
|
||||
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI
|
||||
* 、APP等不同场景生成交易串调起支付。
|
||||
*
|
||||
* @param payPackage
|
||||
* 包含订单信息的对象
|
||||
* @see com.foxinmy.weixin4j.payment.mch.MchPayPackage
|
||||
* @see com.foxinmy.weixin4j.payment.mch.PrePay
|
||||
* @see <a
|
||||
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1">统一下单接口</a>
|
||||
* @return 预支付对象
|
||||
*/
|
||||
public PrePay createPrePay(MchPayPackage payPackage)
|
||||
throws WeixinPayException {
|
||||
if (StringUtil.isBlank(payPackage.getSign())) {
|
||||
payPackage.setSign(DigestUtil.paysignMd5(payPackage,
|
||||
weixinAccount.getPaySignKey()));
|
||||
}
|
||||
String payJsRequestXml = XmlStream.toXML(payPackage);
|
||||
try {
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
PayURLConsts.MCH_UNIFIEDORDER_URL, payJsRequestXml);
|
||||
PrePay prePay = response.getAsObject(new TypeReference<PrePay>() {
|
||||
});
|
||||
if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) {
|
||||
throw new WeixinPayException(prePay.getReturnMsg(),
|
||||
prePay.getReturnCode());
|
||||
}
|
||||
if (!prePay.getResultCode().equalsIgnoreCase(Consts.SUCCESS)) {
|
||||
throw new WeixinPayException(prePay.getResultCode(),
|
||||
prePay.getErrCodeDes());
|
||||
}
|
||||
return prePay;
|
||||
} catch (WeixinException e) {
|
||||
throw new WeixinPayException(e.getErrorCode(), e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成V3.x版本JSAPI支付字符串
|
||||
*
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param body
|
||||
* 订单描述
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额 按实际金额传入即可(元) 构造函数会转换为分
|
||||
* @param notifyUrl
|
||||
* 支付通知地址
|
||||
* @param createIp
|
||||
* ip地址
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 支付json串
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public String createPayJsRequestJson(String openId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, WeixinPayAccount weixinAccount)
|
||||
throws WeixinPayException {
|
||||
return JSON.toJSONString(createPayJsRequest(openId, body, outTradeNo,
|
||||
totalFee, notifyUrl, createIp, null, null, null, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成V3.x版本JSAPI支付对象【完整参数】
|
||||
*
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
|
||||
* @param timeStart
|
||||
* 订单生成时间,格式为yyyyMMddHHmmss
|
||||
* @param timeExpire
|
||||
* 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟
|
||||
* @param goodsTag
|
||||
* 商品标记,代金券或立减优惠功能的参数
|
||||
* @param limitPay
|
||||
* 指定支付方式:no_credit--指定不能使用信用卡支付
|
||||
* @see com.foxinmy.weixin4j.payment.mch.MchPayRequest
|
||||
* @return MchPayRequest对象;<font
|
||||
* color="red">注意:如果要转换为JSON格式请使用fastjson中的JSON对象或者直接用MchPayRequest#
|
||||
* asPayJsRequestJson方法</font>
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public MchPayRequest createPayJsRequest(String openId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, String attach, Date timeStart, Date timeExpire,
|
||||
String goodsTag, String limitPay) throws WeixinPayException {
|
||||
MchPayPackage payPackage = new MchPayPackage(weixinAccount, openId,
|
||||
body, outTradeNo, totalFee, notifyUrl, createIp,
|
||||
TradeType.JSAPI);
|
||||
payPackage.setAttach(attach);
|
||||
payPackage.setTimeStart(timeStart);
|
||||
payPackage.setTimeExpire(timeExpire);
|
||||
payPackage.setGoodsTag(goodsTag);
|
||||
payPackage.setLimitPay(limitPay);
|
||||
payPackage.setSign(DigestUtil.paysignMd5(payPackage,
|
||||
weixinAccount.getPaySignKey()));
|
||||
PrePay prePay = createPrePay(payPackage);
|
||||
MchPayRequest jsPayRequest = new MchPayRequest(prePay);
|
||||
jsPayRequest.setSignType(SignType.MD5);
|
||||
jsPayRequest.setPaySign(DigestUtil.paysignMd5(jsPayRequest,
|
||||
weixinAccount.getPaySignKey()));
|
||||
return jsPayRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V3.x NativePay支付(扫码支付)链接【模式一】
|
||||
*
|
||||
* @param productId
|
||||
* 与订单ID等价
|
||||
* @return 支付链接
|
||||
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一</a>
|
||||
*/
|
||||
public String createNativePayRequestURL(String productId) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
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 = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
return String.format(PayURLConsts.MCH_NATIVE_URL, sign,
|
||||
weixinAccount.getId(), weixinAccount.getMchId(), productId,
|
||||
timestamp, noncestr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V3.x NativePay支付(扫码支付)链接【模式二】【必填参数】
|
||||
*
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @return 支付链接
|
||||
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5">模式二</a>
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public String createNativePayRequestURL(String productId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp) throws WeixinPayException {
|
||||
return createNativePayRequestURL(productId, body, outTradeNo, totalFee,
|
||||
notifyUrl, createIp, null, null, null, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V3.x NativePay支付(扫码支付)链接【模式二】【完整参数】
|
||||
*
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
|
||||
* @param timeStart
|
||||
* 订单生成时间,格式为yyyyMMddHHmmss
|
||||
* @param timeExpire
|
||||
* 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟
|
||||
* @param goodsTag
|
||||
* 商品标记,代金券或立减优惠功能的参数
|
||||
* @param limitPay
|
||||
* 指定支付方式:no_credit--指定不能使用信用卡支付
|
||||
* @return 支付链接
|
||||
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5">模式二</a>
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public String createNativePayRequestURL(String productId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, String attach, Date timeStart, Date timeExpire,
|
||||
String goodsTag, String limitPay) throws WeixinPayException {
|
||||
MchPayPackage payPackage = new MchPayPackage(weixinAccount, null, body,
|
||||
outTradeNo, totalFee, notifyUrl, createIp, TradeType.NATIVE);
|
||||
payPackage.setProductId(productId);
|
||||
payPackage.setAttach(attach);
|
||||
payPackage.setTimeStart(timeStart);
|
||||
payPackage.setTimeExpire(timeExpire);
|
||||
payPackage.setGoodsTag(goodsTag);
|
||||
payPackage.setLimitPay(limitPay);
|
||||
payPackage.setSign(DigestUtil.paysignMd5(payPackage,
|
||||
weixinAccount.getPaySignKey()));
|
||||
PrePay prePay = createPrePay(payPackage);
|
||||
return prePay.getCodeUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交被扫支付
|
||||
*
|
||||
* @param authCode
|
||||
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param orderNo
|
||||
* 商户内部唯一订单号
|
||||
* @param orderFee
|
||||
* 商品总额 单位元
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @return 支付的订单信息
|
||||
* @see {@link #createMicroPay(MicroPayPackage)}
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public Order createMicroPay(String authCode, String body, String orderNo,
|
||||
double orderFee, String createIp) throws WeixinException {
|
||||
MicroPayPackage payPackage = new MicroPayPackage(weixinAccount,
|
||||
authCode, body, orderNo, orderFee, createIp);
|
||||
return createMicroPay(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交被扫支付:收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付.
|
||||
*
|
||||
* @param payPackage
|
||||
* 订单信息
|
||||
* @return 支付的订单信息
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.payment.mch.Order
|
||||
* @see <a
|
||||
* href="http://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10">提交被扫支付API</a>
|
||||
*/
|
||||
public Order createMicroPay(MicroPayPackage payPackage)
|
||||
throws WeixinException {
|
||||
String sign = DigestUtil.paysignMd5(payPackage,
|
||||
weixinAccount.getPaySignKey());
|
||||
payPackage.setSign(sign);
|
||||
String para = XmlStream.toXML(payPackage);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
PayURLConsts.MCH_MICROPAY_URL, para);
|
||||
return response
|
||||
.getAsObject(new TypeReference<com.foxinmy.weixin4j.payment.mch.Order>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单查询
|
||||
* <p>
|
||||
@ -82,7 +358,7 @@ public class Pay3Api {
|
||||
*/
|
||||
public Order orderQuery(IdQuery idQuery) throws WeixinException {
|
||||
Map<String, String> map = baseMap(idQuery);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -142,8 +418,8 @@ public class Pay3Api {
|
||||
refundFeeType = CurrencyType.CNY;
|
||||
}
|
||||
map.put("refund_fee_type", refundFeeType.name());
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map,
|
||||
weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
|
||||
@ -175,7 +451,7 @@ public class Pay3Api {
|
||||
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
|
||||
* @param totalFee
|
||||
* 订单总金额,单位为元
|
||||
* @see {@link #refundApply(InputStream, IdQuery, String, double, double, String, CurrencyType)}
|
||||
* @see {@link #refundApply(InputStream, IdQuery, String, double, double,CurrencyType, String)}
|
||||
*/
|
||||
public RefundResult refundApply(InputStream ca, IdQuery idQuery,
|
||||
String outRefundNo, double totalFee) throws WeixinException {
|
||||
@ -204,8 +480,8 @@ public class Pay3Api {
|
||||
WeixinRequestExecutor weixinExecutor = new WeixinSSLRequestExecutor(
|
||||
weixinAccount.getMchId(), ca);
|
||||
Map<String, String> map = baseMap(idQuery);
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map,
|
||||
weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -241,7 +517,7 @@ public class Pay3Api {
|
||||
} catch (UnsupportedEncodingException ignore) {
|
||||
;
|
||||
}
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -268,7 +544,7 @@ public class Pay3Api {
|
||||
public ApiResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
Map<String, String> map = baseMap(new IdQuery(outTradeNo,
|
||||
IdType.TRADENO));
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -317,7 +593,7 @@ public class Pay3Api {
|
||||
Map<String, String> map = baseMap(null);
|
||||
map.put("bill_date", formatBillDate);
|
||||
map.put("bill_type", billType.name());
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -373,7 +649,7 @@ public class Pay3Api {
|
||||
*/
|
||||
public RefundRecord refundQuery(IdQuery idQuery) throws WeixinException {
|
||||
Map<String, String> map = baseMap(idQuery);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -414,7 +690,7 @@ public class Pay3Api {
|
||||
map.put("user_ip", ip);
|
||||
map.put("time", DateUtil.fortmat2yyyyMMddHHmmss(time));
|
||||
map.putAll((Map<String, String>) JSON.toJSON(returnXml));
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
@ -437,7 +713,7 @@ public class Pay3Api {
|
||||
throws WeixinException {
|
||||
Map<String, String> map = baseMap(null);
|
||||
map.put("auth_code", authCode);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = XmlStream.map2xml(map);
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
|
||||
@ -1,5 +1,15 @@
|
||||
package com.foxinmy.weixin4j.payment;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.type.SignType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
|
||||
/**
|
||||
* 支付URL常量类
|
||||
*
|
||||
@ -108,4 +118,42 @@ public final class PayURLConsts {
|
||||
*/
|
||||
public static final String MCH_AUTHCODE_OPENID_URL = MCH_BASE_URL
|
||||
+ "/tools/authcodetoopenid";
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 生成编辑地址请求
|
||||
* </p>
|
||||
*
|
||||
* err_msg edit_address:ok获取编辑收货地址成功</br> edit_address:fail获取编辑收货地址失败</br>
|
||||
* userName 收货人姓名</br> telNumber 收货人电话</br> addressPostalCode 邮编</br>
|
||||
* proviceFirstStageName 国标收货地址第一级地址</br> addressCitySecondStageName
|
||||
* 国标收货地址第二级地址</br> addressCountiesThirdStageName 国标收货地址第三级地址</br>
|
||||
* addressDetailInfo 详细收货地址信息</br> nationalCode 收货地址国家码</br>
|
||||
*
|
||||
* @param appId
|
||||
* 公众号的ID
|
||||
* @param url
|
||||
* 当前访问页的URL
|
||||
* @param accessToken
|
||||
* snsapi_base授权时产生的token
|
||||
* @return
|
||||
*/
|
||||
public static String createAddressRequestJson(String appId, String url,
|
||||
String accessToken) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
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 = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true,
|
||||
null));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,409 +0,0 @@
|
||||
package com.foxinmy.weixin4j.payment;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinRequestExecutor;
|
||||
import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
|
||||
import com.foxinmy.weixin4j.payment.mch.MchPayRequest;
|
||||
import com.foxinmy.weixin4j.payment.mch.Order;
|
||||
import com.foxinmy.weixin4j.payment.mch.PrePay;
|
||||
import com.foxinmy.weixin4j.type.SignType;
|
||||
import com.foxinmy.weixin4j.type.TradeType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* 支付工具类(JSAPI,NATIVE,MicroPay)
|
||||
*
|
||||
* @className PayUtil
|
||||
* @author jy
|
||||
* @date 2014年10月28日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class PayUtil {
|
||||
|
||||
/**
|
||||
* 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 DigestUtil.MD5(sb.toString()).toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成V3.x版本JSAPI支付字符串
|
||||
*
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param body
|
||||
* 订单描述
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额 按实际金额传入即可(元) 构造函数会转换为分
|
||||
* @param notifyUrl
|
||||
* 支付通知地址
|
||||
* @param createIp
|
||||
* ip地址
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 支付json串
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public static String createPayJsRequestJson(String openId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, WeixinPayAccount weixinAccount)
|
||||
throws WeixinPayException {
|
||||
return JSON.toJSONString(createPayJsRequest(weixinAccount, openId,
|
||||
body, outTradeNo, totalFee, notifyUrl, createIp, null, null,
|
||||
null, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成V3.x版本JSAPI支付对象【完整参数】
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 支付配置信息
|
||||
* @param openId
|
||||
* 用户ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
|
||||
* @param timeStart
|
||||
* 订单生成时间,格式为yyyyMMddHHmmss
|
||||
* @param timeExpire
|
||||
* 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟
|
||||
* @param goodsTag
|
||||
* 商品标记,代金券或立减优惠功能的参数
|
||||
* @param limitPay
|
||||
* 指定支付方式:no_credit--指定不能使用信用卡支付
|
||||
* @see com.foxinmy.weixin4j.payment.mch.MchPayRequest
|
||||
* @return MchPayRequest对象;<font
|
||||
* color="red">注意:如果要转换为JSON格式请使用fastjson包或者直接用MchPayRequest#
|
||||
* asPayJsRequestJson方法</font>
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public static MchPayRequest createPayJsRequest(
|
||||
WeixinPayAccount weixinAccount, String openId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, String attach, Date timeStart, Date timeExpire,
|
||||
String goodsTag, String limitPay) throws WeixinPayException {
|
||||
MchPayPackage payPackage = new MchPayPackage(weixinAccount, openId,
|
||||
body, outTradeNo, totalFee, notifyUrl, createIp,
|
||||
TradeType.JSAPI);
|
||||
payPackage.setAttach(attach);
|
||||
payPackage.setTimeStart(timeStart);
|
||||
payPackage.setTimeExpire(timeExpire);
|
||||
payPackage.setGoodsTag(goodsTag);
|
||||
payPackage.setLimitPay(limitPay);
|
||||
String paySignKey = weixinAccount.getPaySignKey();
|
||||
payPackage.setSign(paysignMd5(payPackage, paySignKey));
|
||||
PrePay prePay = createPrePay(payPackage, paySignKey);
|
||||
MchPayRequest jsPayRequest = new MchPayRequest(prePay);
|
||||
jsPayRequest.setSignType(SignType.MD5);
|
||||
jsPayRequest.setPaySign(paysignMd5(jsPayRequest, paySignKey));
|
||||
return jsPayRequest;
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一下单接口</br>
|
||||
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI
|
||||
* 、APP等不同场景生成交易串调起支付。
|
||||
*
|
||||
* @param payPackage
|
||||
* 包含订单信息的对象
|
||||
* @param paySignKey
|
||||
* <font color="red">如果sign为空 则拿paysignkey进行签名</font>
|
||||
* @see com.foxinmy.weixin4j.payment.mch.MchPayPackage
|
||||
* @see com.foxinmy.weixin4j.payment.mch.PrePay
|
||||
* @see <a
|
||||
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1">统一下单接口</a>
|
||||
* @return 预支付对象
|
||||
*/
|
||||
private final static WeixinRequestExecutor httpClient = new WeixinRequestExecutor();
|
||||
|
||||
public static PrePay createPrePay(MchPayPackage payPackage,
|
||||
String paySignKey) throws WeixinPayException {
|
||||
if (StringUtil.isBlank(payPackage.getSign())) {
|
||||
payPackage.setSign(paysignMd5(payPackage, paySignKey));
|
||||
}
|
||||
String payJsRequestXml = XmlStream.toXML(payPackage);
|
||||
try {
|
||||
WeixinResponse response = httpClient.post(
|
||||
PayURLConsts.MCH_UNIFIEDORDER_URL, payJsRequestXml);
|
||||
PrePay prePay = response.getAsObject(new TypeReference<PrePay>() {
|
||||
});
|
||||
if (!prePay.getReturnCode().equalsIgnoreCase(Consts.SUCCESS)) {
|
||||
throw new WeixinPayException(prePay.getReturnMsg(),
|
||||
prePay.getReturnCode());
|
||||
}
|
||||
if (!prePay.getResultCode().equalsIgnoreCase(Consts.SUCCESS)) {
|
||||
throw new WeixinPayException(prePay.getResultCode(),
|
||||
prePay.getErrCodeDes());
|
||||
}
|
||||
return prePay;
|
||||
} catch (WeixinException e) {
|
||||
throw new WeixinPayException(e.getErrorCode(), e.getErrorMsg());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 生成编辑地址请求
|
||||
* </p>
|
||||
*
|
||||
* err_msg edit_address:ok获取编辑收货地址成功</br> edit_address:fail获取编辑收货地址失败</br>
|
||||
* userName 收货人姓名</br> telNumber 收货人电话</br> addressPostalCode 邮编</br>
|
||||
* proviceFirstStageName 国标收货地址第一级地址</br> addressCitySecondStageName
|
||||
* 国标收货地址第二级地址</br> addressCountiesThirdStageName 国标收货地址第三级地址</br>
|
||||
* addressDetailInfo 详细收货地址信息</br> nationalCode 收货地址国家码</br>
|
||||
*
|
||||
* @param appId
|
||||
* 公众号的ID
|
||||
* @param url
|
||||
* 当前访问页的URL
|
||||
* @param accessToken
|
||||
* snsapi_base授权时产生的token
|
||||
* @return
|
||||
*/
|
||||
public static String createAddressRequestJson(String appId, String url,
|
||||
String accessToken) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
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 = DigestUtil.SHA1(MapUtil.toJoinString(map, false, true,
|
||||
null));
|
||||
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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V3.x NativePay支付(扫码支付)链接【模式一】
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 支付配置信息
|
||||
* @param productId
|
||||
* 与订单ID等价
|
||||
* @return 支付链接
|
||||
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4">模式一</a>
|
||||
*/
|
||||
public static String createNativePayRequestURL(
|
||||
WeixinPayAccount weixinAccount, String productId) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
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(PayURLConsts.MCH_NATIVE_URL, sign,
|
||||
weixinAccount.getId(), weixinAccount.getMchId(), productId,
|
||||
timestamp, noncestr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V3.x NativePay支付(扫码支付)链接【模式二】【必填参数】
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 支付配置信息
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @return 支付链接
|
||||
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5">模式二</a>
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public static String createNativePayRequestURL(
|
||||
WeixinPayAccount weixinAccount, String productId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp) throws WeixinPayException {
|
||||
return createNativePayRequestURL(weixinAccount, productId, body,
|
||||
outTradeNo, totalFee, notifyUrl, createIp, null, null, null,
|
||||
null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V3.x NativePay支付(扫码支付)链接【模式二】【完整参数】
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 支付配置信息
|
||||
* @param productId
|
||||
* 商品ID
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param outTradeNo
|
||||
* 商户内部唯一订单号
|
||||
* @param totalFee
|
||||
* 商品总额 单位元
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
|
||||
* @param timeStart
|
||||
* 订单生成时间,格式为yyyyMMddHHmmss
|
||||
* @param timeExpire
|
||||
* 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟
|
||||
* @param goodsTag
|
||||
* 商品标记,代金券或立减优惠功能的参数
|
||||
* @param limitPay
|
||||
* 指定支付方式:no_credit--指定不能使用信用卡支付
|
||||
* @return 支付链接
|
||||
* @see <a href="http://pay.weixin.qq.com/wiki/doc/api/native.php">扫码支付</a>
|
||||
* @see <a
|
||||
* href="https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5">模式二</a>
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public static String createNativePayRequestURL(
|
||||
WeixinPayAccount weixinAccount, String productId, String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, String attach, Date timeStart, Date timeExpire,
|
||||
String goodsTag, String limitPay) throws WeixinPayException {
|
||||
MchPayPackage payPackage = new MchPayPackage(weixinAccount, null, body,
|
||||
outTradeNo, totalFee, notifyUrl, createIp, TradeType.NATIVE);
|
||||
payPackage.setProductId(productId);
|
||||
payPackage.setAttach(attach);
|
||||
payPackage.setTimeStart(timeStart);
|
||||
payPackage.setTimeExpire(timeExpire);
|
||||
payPackage.setGoodsTag(goodsTag);
|
||||
payPackage.setLimitPay(limitPay);
|
||||
String paySignKey = weixinAccount.getPaySignKey();
|
||||
payPackage.setSign(paysignMd5(payPackage, paySignKey));
|
||||
PrePay prePay = createPrePay(payPackage, paySignKey);
|
||||
return prePay.getCodeUrl();
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交被扫支付
|
||||
*
|
||||
* @param authCode
|
||||
* 扫码支付授权码 ,设备读取用户微信中的条码或者二维码信息
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param orderNo
|
||||
* 商户内部唯一订单号
|
||||
* @param orderFee
|
||||
* 商品总额 单位元
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 支付的订单信息
|
||||
* @see {@link #createMicroPay(MicroPayPackage, WeixinPayAccount)}
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static Order createMicroPay(String authCode, String body,
|
||||
String orderNo, double orderFee, String createIp,
|
||||
WeixinPayAccount weixinAccount) throws WeixinException {
|
||||
MicroPayPackage payPackage = new MicroPayPackage(weixinAccount,
|
||||
authCode, body, orderNo, orderFee, createIp);
|
||||
return createMicroPay(payPackage, weixinAccount);
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交被扫支付:收银员使用扫码设备读取微信用户刷卡授权码以后,二维码或条码信息传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付.
|
||||
*
|
||||
* @param payPackage
|
||||
* 订单信息
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 支付的订单信息
|
||||
* @throws WeixinException
|
||||
* @see com.foxinmy.weixin4j.payment.mch.Order
|
||||
* @see <a
|
||||
* href="http://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10">提交被扫支付API</a>
|
||||
*/
|
||||
public static Order createMicroPay(MicroPayPackage payPackage,
|
||||
WeixinPayAccount weixinAccount) throws WeixinException {
|
||||
String sign = paysignMd5(payPackage, weixinAccount.getPaySignKey());
|
||||
payPackage.setSign(sign);
|
||||
String para = XmlStream.toXML(payPackage);
|
||||
WeixinResponse response = httpClient.post(
|
||||
PayURLConsts.MCH_MICROPAY_URL, para);
|
||||
return response
|
||||
.getAsObject(new TypeReference<com.foxinmy.weixin4j.payment.mch.Order>() {
|
||||
});
|
||||
}
|
||||
|
||||
private static String JSAPI() throws WeixinPayException {
|
||||
WeixinPayAccount weixinAccount = JSON.parseObject(
|
||||
Weixin4jConfigUtil.getValue("account"), WeixinPayAccount.class);
|
||||
return createPayJsRequestJson("oyFLst1bqtuTcxK-ojF8hOGtLQao", "支付测试",
|
||||
"JSAPI01", 0.01d, "http://127.0.0.1/jsapi/notify", "127.0.0.0",
|
||||
weixinAccount);
|
||||
}
|
||||
|
||||
private static String NATIVE() {
|
||||
WeixinPayAccount weixinAccount = JSON.parseObject(
|
||||
Weixin4jConfigUtil.getValue("account"), WeixinPayAccount.class);
|
||||
return createNativePayRequestURL(weixinAccount, "P1");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws WeixinPayException {
|
||||
// V3版本下的JS支付
|
||||
System.out.println(JSAPI());
|
||||
// V3版本下的原生支付
|
||||
System.out.println(NATIVE());
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,8 @@
|
||||
|
||||
**在`2014年10月9号`之前申请并审核通过的支付接口应该属于`V2版本`支付,而之后申请的接口则为`V3版本(商户平台)`支付**
|
||||
|
||||
[PayUtil](./PayUtil.java)
|
||||
|
||||
[Pay3Api](../api/Pay3Api.java)
|
||||
-------------------------
|
||||
|
||||
* createPayJsRequestJson: 创建V3版本(商户平台)的JSAPI支付串
|
||||
@ -17,12 +18,6 @@
|
||||
|
||||
* createMicroPay: 创建刷卡支付(商户平台)请求
|
||||
|
||||
* createAddressRequestJson: 生成编辑收货地址请求串
|
||||
|
||||
|
||||
[Pay3Api](../api/Pay3Api.java)
|
||||
-------------------------
|
||||
|
||||
* orderQuery: 订单查询接口
|
||||
|
||||
* refundOrder: 退款申请接口
|
||||
@ -39,6 +34,10 @@
|
||||
[Pay2Api](https://github.com/foxinmy/weixin4j/blob/master/weixin4j-mp/src/main/java/com/foxinmy/weixin4j/mp/api/Pay2Api.java)
|
||||
-------------------------
|
||||
|
||||
* createPayJsRequestJson: 创建V2版本的JSAPI支付串
|
||||
|
||||
* createNativePayRequestURL: 创建V2版本的扫码支付链接
|
||||
|
||||
* orderQuery: 订单查询接口
|
||||
|
||||
* refundOrder: 退款申请接口
|
||||
|
||||
@ -11,6 +11,7 @@ import com.foxinmy.weixin4j.api.CashApi;
|
||||
import com.foxinmy.weixin4j.api.CouponApi;
|
||||
import com.foxinmy.weixin4j.api.Pay3Api;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.payment.coupon.CouponDetail;
|
||||
@ -21,7 +22,9 @@ import com.foxinmy.weixin4j.payment.mch.AuthCodeOpenIdResult;
|
||||
import com.foxinmy.weixin4j.payment.mch.MPPayment;
|
||||
import com.foxinmy.weixin4j.payment.mch.MPPaymentRecord;
|
||||
import com.foxinmy.weixin4j.payment.mch.MPPaymentResult;
|
||||
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
|
||||
import com.foxinmy.weixin4j.payment.mch.Order;
|
||||
import com.foxinmy.weixin4j.payment.mch.PrePay;
|
||||
import com.foxinmy.weixin4j.payment.mch.Redpacket;
|
||||
import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
|
||||
import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
|
||||
@ -48,8 +51,6 @@ public class WeixinPayProxy {
|
||||
private final CouponApi couponApi;
|
||||
private final CashApi cashApi;
|
||||
|
||||
private final String DEFAULT_CA_FILE;
|
||||
|
||||
/**
|
||||
* 使用weixin4j.properties配置的账号信息
|
||||
*/
|
||||
@ -68,8 +69,24 @@ public class WeixinPayProxy {
|
||||
this.pay3Api = new Pay3Api(weixinAccount);
|
||||
this.couponApi = new CouponApi(weixinAccount);
|
||||
this.cashApi = new CashApi(weixinAccount);
|
||||
this.DEFAULT_CA_FILE = Weixin4jConfigUtil.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH);
|
||||
}
|
||||
|
||||
/**
|
||||
* 统一下单接口</br>
|
||||
* 除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI
|
||||
* 、APP等不同场景生成交易串调起支付。
|
||||
*
|
||||
* @param payPackage
|
||||
* 包含订单信息的对象
|
||||
* @see com.foxinmy.weixin4j.payment.mch.MchPayPackage
|
||||
* @see com.foxinmy.weixin4j.payment.mch.PrePay
|
||||
* @see <a
|
||||
* href="http://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1">统一下单接口</a>
|
||||
* @return 预支付对象
|
||||
*/
|
||||
public PrePay createPrePay(MchPayPackage payPackage)
|
||||
throws WeixinPayException {
|
||||
return pay3Api.createPrePay(payPackage);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -150,8 +167,12 @@ public class WeixinPayProxy {
|
||||
public com.foxinmy.weixin4j.payment.mch.RefundResult refundApply(
|
||||
IdQuery idQuery, String outRefundNo, double totalFee)
|
||||
throws WeixinException, IOException {
|
||||
return pay3Api.refundApply(new FileInputStream(DEFAULT_CA_FILE),
|
||||
idQuery, outRefundNo, totalFee);
|
||||
return pay3Api
|
||||
.refundApply(
|
||||
new FileInputStream(Weixin4jConfigUtil
|
||||
.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH)),
|
||||
idQuery, outRefundNo, totalFee);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -236,8 +257,12 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public ApiResult reverseOrder(IdQuery idQuery) throws WeixinException,
|
||||
IOException {
|
||||
return pay3Api.reverseOrder(new FileInputStream(DEFAULT_CA_FILE),
|
||||
idQuery);
|
||||
return pay3Api
|
||||
.reverseOrder(
|
||||
new FileInputStream(Weixin4jConfigUtil
|
||||
.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH)),
|
||||
idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -344,8 +369,12 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public CouponResult sendCoupon(String couponStockId, String partnerTradeNo,
|
||||
String openId) throws WeixinException, IOException {
|
||||
return couponApi.sendCoupon(new FileInputStream(DEFAULT_CA_FILE),
|
||||
couponStockId, partnerTradeNo, openId, null);
|
||||
return couponApi
|
||||
.sendCoupon(
|
||||
new FileInputStream(Weixin4jConfigUtil
|
||||
.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH)),
|
||||
couponStockId, partnerTradeNo, openId, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -409,8 +438,12 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public RedpacketSendResult sendRedpack(Redpacket redpacket)
|
||||
throws WeixinException, IOException {
|
||||
return cashApi.sendRedpack(new FileInputStream(DEFAULT_CA_FILE),
|
||||
redpacket);
|
||||
return cashApi
|
||||
.sendRedpack(
|
||||
new FileInputStream(Weixin4jConfigUtil
|
||||
.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH)),
|
||||
redpacket);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -439,8 +472,12 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public RedpacketRecord queryRedpack(String outTradeNo)
|
||||
throws WeixinException, IOException {
|
||||
return cashApi.queryRedpack(new FileInputStream(DEFAULT_CA_FILE),
|
||||
outTradeNo);
|
||||
return cashApi
|
||||
.queryRedpack(
|
||||
new FileInputStream(Weixin4jConfigUtil
|
||||
.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH)),
|
||||
outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -470,8 +507,12 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public MPPaymentResult mpPayment(MPPayment mpPayment)
|
||||
throws WeixinException, IOException {
|
||||
return cashApi.mchPayment(new FileInputStream(DEFAULT_CA_FILE),
|
||||
mpPayment);
|
||||
return cashApi
|
||||
.mchPayment(
|
||||
new FileInputStream(Weixin4jConfigUtil
|
||||
.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH)),
|
||||
mpPayment);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -500,8 +541,12 @@ public class WeixinPayProxy {
|
||||
*/
|
||||
public MPPaymentRecord mpPaymentQuery(String outTradeNo)
|
||||
throws WeixinException, IOException {
|
||||
return cashApi.mchPaymentQuery(new FileInputStream(DEFAULT_CA_FILE),
|
||||
outTradeNo);
|
||||
return cashApi
|
||||
.mchPaymentQuery(
|
||||
new FileInputStream(Weixin4jConfigUtil
|
||||
.getClassPathValue("certificate.file",
|
||||
Weixin4jConst.DEFAULT_CAFILE_PATH)),
|
||||
outTradeNo);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -8,8 +8,8 @@ import javax.xml.bind.annotation.XmlTransient;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.payment.PayRequest;
|
||||
import com.foxinmy.weixin4j.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.type.SignType;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
|
||||
/**
|
||||
* JS支付:get_brand_wcpay_request</br>
|
||||
@ -71,7 +71,7 @@ public class MchPayRequest extends PayRequest {
|
||||
@JSONField(serialize = false)
|
||||
public String asPayJsRequestJson(String paySignKey) {
|
||||
this.setSignType(SignType.MD5);
|
||||
this.setPaySign(PayUtil.paysignMd5(this, paySignKey));
|
||||
this.setPaySign(DigestUtil.paysignMd5(this, paySignKey));
|
||||
return asPayJsRequestJson();
|
||||
}
|
||||
|
||||
|
||||
@ -2,19 +2,22 @@ package com.foxinmy.weixin4j.payment.mch;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* Native支付时的回调响应
|
||||
*
|
||||
* @className NativePayResponseV3
|
||||
* @className NativePayResponse
|
||||
* @author jy
|
||||
* @date 2014年10月28日
|
||||
* @since JDK 1.6
|
||||
@ -26,10 +29,7 @@ public class NativePayResponse extends ApiResult {
|
||||
|
||||
private static final long serialVersionUID = 6119895998783333012L;
|
||||
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
private PrePay prePay;
|
||||
|
||||
@XmlElement(name = "prepay_id")
|
||||
@JSONField(name = "prepay_id")
|
||||
private String prepayId;
|
||||
|
||||
@ -38,7 +38,7 @@ public class NativePayResponse extends ApiResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* 一般作为校验失败时返回
|
||||
* 作为return_code 为 FAIL 的时候返回
|
||||
*
|
||||
* @param returnMsg
|
||||
* 失败消息
|
||||
@ -56,33 +56,53 @@ public class NativePayResponse extends ApiResult {
|
||||
/**
|
||||
* 作为return_code 为 SUCCESS 的时候返回
|
||||
*
|
||||
* @param payPackage
|
||||
* 订单信息
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param prepayId
|
||||
* 调用统一下单接口生成的预支付ID
|
||||
* @throws WeixinPayException
|
||||
*/
|
||||
public NativePayResponse(MchPayPackage payPackage, String paysignKey)
|
||||
throws WeixinPayException {
|
||||
public NativePayResponse(WeixinPayAccount weixinAccount, String prepayId) {
|
||||
super.setReturnCode(Consts.SUCCESS);
|
||||
this.setResultCode(Consts.SUCCESS);
|
||||
this.setMchId(payPackage.getMchId());
|
||||
this.setAppId(payPackage.getAppId());
|
||||
this.setMchId(weixinAccount.getMchId());
|
||||
this.setAppId(weixinAccount.getId());
|
||||
this.setNonceStr(RandomUtil.generateString(16));
|
||||
this.prePay = PayUtil.createPrePay(payPackage, paysignKey);
|
||||
this.prepayId = prePay.getPrepayId();
|
||||
this.prepayId = prepayId;
|
||||
}
|
||||
|
||||
public String getPrepayId() {
|
||||
return prepayId;
|
||||
}
|
||||
|
||||
public void setPrepayId(String prepayId) {
|
||||
this.prepayId = prepayId;
|
||||
/**
|
||||
* 针对已签名的 NativePayResponse
|
||||
*
|
||||
* @return native回调字符串
|
||||
*/
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
public String asRequestXml() {
|
||||
return XmlStream.toXML(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* 针对未签名的 NativePayResponse
|
||||
*
|
||||
* @param paySignKey
|
||||
* 支付签名密钥
|
||||
* @return native回调字符串
|
||||
*/
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
public String asRequestXml(String paysignKey) {
|
||||
this.setSign(DigestUtil.paysignMd5(this, paysignKey));
|
||||
return XmlStream.toXML(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NativePayResponseV3 [prePay=" + prePay + ", prepayId="
|
||||
+ prepayId + ", " + super.toString() + "]";
|
||||
return "NativePayResponse [prepayId=" + prepayId + ", "
|
||||
+ super.toString() + "]";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -2,6 +2,8 @@ package com.foxinmy.weixin4j.util;
|
||||
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
|
||||
@ -59,4 +61,43 @@ public final class DigestUtil {
|
||||
byte[] data = StringUtil.getBytesUtf8(content);
|
||||
return HexUtil.encodeHexString(getDigest(Consts.MD5).digest(data));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 MD5(sb.toString()).toUpperCase();
|
||||
}
|
||||
|
||||
/**
|
||||
* sha签名(一般用于V2.x支付接口)
|
||||
*
|
||||
* @param obj
|
||||
* 签名对象
|
||||
* @param paySignKey
|
||||
* 支付API的密钥<font color="red">请注意排序放进去的是put("appKey",
|
||||
* paySignKey)</font>
|
||||
* @return
|
||||
*/
|
||||
public static String paysignSha(Object obj, String paySignKey) {
|
||||
Map<String, String> extra = new HashMap<String, String>();
|
||||
if (StringUtil.isNotBlank(paySignKey)) {
|
||||
extra.put("appKey", paySignKey);
|
||||
}
|
||||
return SHA1(MapUtil.toJoinString(obj, false, true, extra));
|
||||
}
|
||||
}
|
||||
|
||||
@ -34,12 +34,12 @@ import com.foxinmy.weixin4j.http.weixin.WeixinSSLRequestExecutor;
|
||||
import com.foxinmy.weixin4j.model.Consts;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.JsPayRequestV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.OrderV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.PayUtil2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.PayPackageV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.RefundRecordV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.RefundResultV2;
|
||||
import com.foxinmy.weixin4j.mp.token.WeixinTokenCreator;
|
||||
import com.foxinmy.weixin4j.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.token.TokenHolder;
|
||||
import com.foxinmy.weixin4j.token.TokenStorager;
|
||||
import com.foxinmy.weixin4j.type.BillType;
|
||||
@ -49,6 +49,7 @@ import com.foxinmy.weixin4j.type.SignType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.util.StringUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConst;
|
||||
@ -84,6 +85,98 @@ public class Pay2Api extends MpApi {
|
||||
tokenStorager);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成V2.x版本JSAPI支付字符串
|
||||
*
|
||||
* @param body
|
||||
* 支付详情
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额 按实际金额传入即可(元) 构造函数会转换为分
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @return 支付json串
|
||||
*/
|
||||
public String createPayJsRequestJson(String body, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp) {
|
||||
return createPayJsRequestJson(body, outTradeNo, totalFee, notifyUrl,
|
||||
createIp, null, null, null, 0d, 0d, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成V2.x版本JSAPI支付字符串
|
||||
*
|
||||
* @param body
|
||||
* 支付详情
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额 按实际金额传入即可(元) 构造函数会转换为分
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
|
||||
* @param timeStart
|
||||
* 订单生成时间,格式为yyyyMMddHHmmss
|
||||
* @param timeExpire
|
||||
* 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟
|
||||
* @param transportFee
|
||||
* 物流费用 如有值 必须保证 transportFee+productFee=totalFee
|
||||
* @param transportFee
|
||||
* 商品费用 如有值 必须保证 transportFee+productFee=totalFee
|
||||
* @param goodsTag
|
||||
* 商品标记,代金券或立减优惠功能的参数
|
||||
* @return 支付json串
|
||||
*/
|
||||
public String createPayJsRequestJson(String body, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp, String attach,
|
||||
Date timeStart, Date timeExpire, double transportFee,
|
||||
double productFee, String goodsTag) {
|
||||
PayPackageV2 payPackage = new PayPackageV2(
|
||||
weixinAccount.getPartnerId(), body, outTradeNo, totalFee,
|
||||
notifyUrl, createIp);
|
||||
payPackage.setAttach(attach);
|
||||
payPackage.setTimeStart(timeStart);
|
||||
payPackage.setTimeExpire(timeExpire);
|
||||
payPackage.setTransportFee(transportFee);
|
||||
payPackage.setProductFee(productFee);
|
||||
payPackage.setGoodsTag(goodsTag);
|
||||
JsPayRequestV2 jsPayRequest = new JsPayRequestV2(weixinAccount,
|
||||
payPackage);
|
||||
jsPayRequest.setPaySign(DigestUtil.paysignSha(jsPayRequest,
|
||||
weixinAccount.getPaySignKey()));
|
||||
jsPayRequest.setSignType(SignType.SHA1);
|
||||
return JSON.toJSONString(jsPayRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V2.x NativePay支付链接
|
||||
*
|
||||
* @param productId
|
||||
* 与订单ID等价
|
||||
* @return 支付链接
|
||||
*/
|
||||
public String createNativePayRequestURL(String productId) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
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 = DigestUtil.paysignSha(map, null);
|
||||
return String
|
||||
.format("weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s×tamp=%s&nocestr=%s",
|
||||
sign, weixinAccount.getId(), productId, timestamp,
|
||||
noncestr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 订单查询
|
||||
*
|
||||
@ -113,7 +206,7 @@ public class Pay2Api extends MpApi {
|
||||
obj.put("appkey", weixinAccount.getPaySignKey());
|
||||
obj.put("package", sb.toString());
|
||||
obj.put("timestamp", timestamp);
|
||||
String signature = PayUtil2.paysignSha(obj);
|
||||
String signature = DigestUtil.paysignSha(obj, null);
|
||||
|
||||
obj.clear();
|
||||
obj.put("appid", weixinAccount.getId());
|
||||
@ -190,8 +283,8 @@ public class Pay2Api extends MpApi {
|
||||
if (mopara != null && !mopara.isEmpty()) {
|
||||
map.putAll(mopara);
|
||||
}
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPartnerKey());
|
||||
String sign = DigestUtil.paysignMd5(map,
|
||||
weixinAccount.getPartnerKey());
|
||||
map.put("sign", sign.toUpperCase());
|
||||
|
||||
SSLContext ctx = null;
|
||||
@ -426,7 +519,7 @@ public class Pay2Api extends MpApi {
|
||||
map.put("input_charset", Consts.UTF_8.name());
|
||||
map.put("partner", weixinAccount.getPartnerId());
|
||||
map.put(idQuery.getType().getName(), idQuery.getId());
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPartnerKey());
|
||||
String sign = DigestUtil.paysignMd5(map, weixinAccount.getPartnerKey());
|
||||
map.put("sign", sign.toLowerCase());
|
||||
WeixinResponse response = weixinExecutor.get(refundquery_uri, map);
|
||||
return ListsuffixResultDeserializer.deserialize(response.getAsString(),
|
||||
@ -464,7 +557,7 @@ public class Pay2Api extends MpApi {
|
||||
map.put("deliver_timestamp", DateUtil.timestamp2string());
|
||||
map.put("deliver_status", status ? "1" : "0");
|
||||
map.put("deliver_msg", statusMsg);
|
||||
map.put("app_signature", PayUtil2.paysignSha(map));
|
||||
map.put("app_signature", DigestUtil.paysignSha(map, null));
|
||||
map.put("sign_method", SignType.SHA1.name().toLowerCase());
|
||||
|
||||
WeixinResponse response = weixinExecutor.post(
|
||||
|
||||
@ -1,12 +1,20 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v2;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlElement;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlTransient;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONField;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* V2 Native支付时的回调响应
|
||||
@ -35,6 +43,10 @@ public class NativePayResponseV2 extends JsPayRequestV2 {
|
||||
@XmlElement(name = "RetErrMsg")
|
||||
private String retMsg;
|
||||
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
private WeixinPayAccount weixinAccount;
|
||||
|
||||
protected NativePayResponseV2() {
|
||||
// jaxb required
|
||||
}
|
||||
@ -44,6 +56,7 @@ public class NativePayResponseV2 extends JsPayRequestV2 {
|
||||
super(weixinAccount, payPackage);
|
||||
this.retCode = "0";
|
||||
this.retMsg = "OK";
|
||||
this.weixinAccount = weixinAccount;
|
||||
}
|
||||
|
||||
public String getRetCode() {
|
||||
@ -62,6 +75,26 @@ public class NativePayResponseV2 extends JsPayRequestV2 {
|
||||
this.retMsg = retMsg;
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成 回调字符串
|
||||
*
|
||||
* @return native回调字符串
|
||||
*/
|
||||
@XmlTransient
|
||||
@JSONField(serialize = false)
|
||||
public String asReqeustXml() {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getId());
|
||||
map.put("appkey", weixinAccount.getPaySignKey());
|
||||
map.put("timestamp", DateUtil.timestamp2string());
|
||||
map.put("noncestr", RandomUtil.generateString(16));
|
||||
map.put("package", getPackageInfo());
|
||||
map.put("retcode", getRetCode());
|
||||
map.put("reterrmsg", getRetMsg());
|
||||
this.setPaySign(DigestUtil.paysignSha(map, null));
|
||||
return XmlStream.toXML(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NativePayResponseV2 [retCode=" + retCode + ", retMsg=" + retMsg
|
||||
|
||||
@ -1,203 +0,0 @@
|
||||
package com.foxinmy.weixin4j.mp.payment.v2;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.type.SignType;
|
||||
import com.foxinmy.weixin4j.util.DateUtil;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.MapUtil;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||
import com.foxinmy.weixin4j.xml.XmlStream;
|
||||
|
||||
/**
|
||||
* V2支付工具类(JSAPI,NATIVE)
|
||||
*
|
||||
* @className PayUtil2
|
||||
* @author jy
|
||||
* @date 2014年10月28日
|
||||
* @since JDK 1.6
|
||||
* @see
|
||||
*/
|
||||
public class PayUtil2 {
|
||||
|
||||
/**
|
||||
* 生成V2.x版本JSAPI支付字符串
|
||||
*
|
||||
* @param body
|
||||
* 支付详情
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额 按实际金额传入即可(元) 构造函数会转换为分
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 支付json串
|
||||
*/
|
||||
public static String createPayJsRequestJsonV2(String body,
|
||||
String outTradeNo, double totalFee, String notifyUrl,
|
||||
String createIp, WeixinPayAccount weixinAccount) {
|
||||
return createPayJsRequestJsonV2(weixinAccount, body, outTradeNo,
|
||||
totalFee, notifyUrl, createIp, null, null, null, 0d, 0d, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 生成V2.x版本JSAPI支付字符串
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param body
|
||||
* 支付详情
|
||||
* @param outTradeNo
|
||||
* 订单号
|
||||
* @param totalFee
|
||||
* 订单总额 按实际金额传入即可(元) 构造函数会转换为分
|
||||
* @param notifyUrl
|
||||
* 支付回调URL
|
||||
* @param createIp
|
||||
* 订单生成的机器 IP
|
||||
* @param attach
|
||||
* 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
|
||||
* @param timeStart
|
||||
* 订单生成时间,格式为yyyyMMddHHmmss
|
||||
* @param timeExpire
|
||||
* 订单失效时间,格式为yyyyMMddHHmmss;注意:最短失效时间间隔必须大于5分钟
|
||||
* @param transportFee
|
||||
* 物流费用 如有值 必须保证 transportFee+productFee=totalFee
|
||||
* @param transportFee
|
||||
* 商品费用 如有值 必须保证 transportFee+productFee=totalFee
|
||||
* @param goodsTag
|
||||
* 商品标记,代金券或立减优惠功能的参数
|
||||
* @return 支付json串
|
||||
*/
|
||||
public static String createPayJsRequestJsonV2(
|
||||
WeixinPayAccount weixinAccount, String body, String outTradeNo,
|
||||
double totalFee, String notifyUrl, String createIp, String attach,
|
||||
Date timeStart, Date timeExpire, double transportFee,
|
||||
double productFee, String goodsTag) {
|
||||
PayPackageV2 payPackage = new PayPackageV2(
|
||||
weixinAccount.getPartnerId(), body, outTradeNo, totalFee,
|
||||
notifyUrl, createIp);
|
||||
payPackage.setAttach(attach);
|
||||
payPackage.setTimeStart(timeStart);
|
||||
payPackage.setTimeExpire(timeExpire);
|
||||
payPackage.setTransportFee(transportFee);
|
||||
payPackage.setProductFee(productFee);
|
||||
payPackage.setGoodsTag(goodsTag);
|
||||
JsPayRequestV2 jsPayRequest = new JsPayRequestV2(weixinAccount,
|
||||
payPackage);
|
||||
jsPayRequest.setPaySign(paysignSha(jsPayRequest,
|
||||
weixinAccount.getPaySignKey()));
|
||||
jsPayRequest.setSignType(SignType.SHA1);
|
||||
return JSON.toJSONString(jsPayRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
* sha签名(一般用于V2.x支付接口)
|
||||
*
|
||||
* @param obj
|
||||
* 签名对象
|
||||
* @return
|
||||
*/
|
||||
public static String paysignSha(Object obj) {
|
||||
return DigestUtil.SHA1(MapUtil.toJoinString(obj, false, true, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* sha签名(一般用于V2.x支付接口)
|
||||
*
|
||||
* @param obj
|
||||
* 签名对象
|
||||
* @param paySignKey
|
||||
* 支付API的密钥<font color="red">请注意排序放进去的是put("appKey",
|
||||
* paySignKey)</font>
|
||||
* @return
|
||||
*/
|
||||
public static String paysignSha(Object obj, String paySignKey) {
|
||||
Map<String, String> extra = new HashMap<String, String>();
|
||||
extra.put("appKey", paySignKey);
|
||||
return DigestUtil.SHA1(MapUtil.toJoinString(obj, false, true, extra));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V2.x NativePay支付链接
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param productId
|
||||
* 与订单ID等价
|
||||
* @return 支付链接
|
||||
*/
|
||||
public static String createNativePayRequestURLV2(
|
||||
WeixinPayAccount weixinAccount, String productId) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
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("weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s×tamp=%s&nocestr=%s",
|
||||
sign, weixinAccount.getId(), productId, timestamp,
|
||||
noncestr);
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建V2.x NATIVE回调时的响应字符串
|
||||
*
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @param payPackage
|
||||
* 订单信息
|
||||
* @return
|
||||
*/
|
||||
public static String createNativePayResponseV2(
|
||||
WeixinPayAccount weixinAccount, PayPackageV2 payPackage) {
|
||||
NativePayResponseV2 payRequest = new NativePayResponseV2(weixinAccount,
|
||||
payPackage);
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
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.toXML(payRequest);
|
||||
}
|
||||
|
||||
private static String JSAPIV2() {
|
||||
WeixinPayAccount weixinAccount = JSON.parseObject(
|
||||
Weixin4jConfigUtil.getValue("account"), WeixinPayAccount.class);
|
||||
return createPayJsRequestJsonV2("支付测试", "JSAPI01", 0.01d, "127.0.0.0",
|
||||
"http://127.0.0.1/jsapi/notify", weixinAccount);
|
||||
}
|
||||
|
||||
private static String NATIVEV2() {
|
||||
WeixinPayAccount weixinAccount = JSON.parseObject(
|
||||
Weixin4jConfigUtil.getValue("account"), WeixinPayAccount.class);
|
||||
return createNativePayRequestURLV2(weixinAccount, "P1");
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws WeixinPayException {
|
||||
// V2版本下的JS支付
|
||||
System.out.println(JSAPIV2());
|
||||
// V2版本下的原生支付
|
||||
System.out.println(NATIVEV2());
|
||||
}
|
||||
}
|
||||
@ -9,12 +9,11 @@ import java.util.Date;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinPayException;
|
||||
import com.foxinmy.weixin4j.http.weixin.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.WeixinPayAccount;
|
||||
import com.foxinmy.weixin4j.mp.api.Pay2Api;
|
||||
import com.foxinmy.weixin4j.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.payment.WeixinPayProxy;
|
||||
import com.foxinmy.weixin4j.payment.mch.ApiResult;
|
||||
import com.foxinmy.weixin4j.payment.mch.MchPayPackage;
|
||||
@ -24,6 +23,7 @@ import com.foxinmy.weixin4j.token.FileTokenStorager;
|
||||
import com.foxinmy.weixin4j.type.IdQuery;
|
||||
import com.foxinmy.weixin4j.type.IdType;
|
||||
import com.foxinmy.weixin4j.type.TradeType;
|
||||
import com.foxinmy.weixin4j.util.DigestUtil;
|
||||
import com.foxinmy.weixin4j.util.Weixin4jConfigUtil;
|
||||
|
||||
public class PayTest {
|
||||
@ -84,7 +84,7 @@ public class PayTest {
|
||||
System.err.println(order);
|
||||
String sign = order.getSign();
|
||||
order.setSign(null);
|
||||
String valiSign = PayUtil.paysignMd5(order, ACCOUNT3.getPaySignKey());
|
||||
String valiSign = DigestUtil.paysignMd5(order, ACCOUNT3.getPaySignKey());
|
||||
System.err
|
||||
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||
Assert.assertEquals(valiSign, sign);
|
||||
@ -98,7 +98,7 @@ public class PayTest {
|
||||
// 这里的验证签名需要把details循环拼接
|
||||
String sign = record.getSign();
|
||||
record.setSign(null);
|
||||
String valiSign = PayUtil.paysignMd5(record, ACCOUNT3.getPaySignKey());
|
||||
String valiSign = DigestUtil.paysignMd5(record, ACCOUNT3.getPaySignKey());
|
||||
System.err
|
||||
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||
Assert.assertEquals(valiSign, sign);
|
||||
@ -127,7 +127,7 @@ public class PayTest {
|
||||
System.err.println(result);
|
||||
String sign = result.getSign();
|
||||
result.setSign(null);
|
||||
String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
||||
String valiSign = DigestUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
||||
System.err
|
||||
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||
Assert.assertEquals(valiSign, sign);
|
||||
@ -141,8 +141,7 @@ public class PayTest {
|
||||
payPackageV3.setProductId("0001");
|
||||
PrePay prePay = null;
|
||||
try {
|
||||
prePay = PayUtil.createPrePay(payPackageV3,
|
||||
ACCOUNT3.getPaySignKey());
|
||||
prePay = PAY3.createPrePay(payPackageV3);
|
||||
} catch (WeixinPayException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -155,7 +154,7 @@ public class PayTest {
|
||||
System.err.println(result);
|
||||
String sign = result.getSign();
|
||||
result.setSign(null);
|
||||
String valiSign = PayUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
||||
String valiSign = DigestUtil.paysignMd5(result, ACCOUNT3.getPaySignKey());
|
||||
System.err
|
||||
.println(String.format("sign=%s,valiSign=%s", sign, valiSign));
|
||||
Assert.assertEquals(valiSign, sign);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user