删除PayUtil类,接口转移到PayApi类 #16

This commit is contained in:
jinyu 2015-12-19 16:41:48 +08:00
parent b21d61144a
commit 0a1cad7341
16 changed files with 649 additions and 698 deletions

View File

@ -553,3 +553,8 @@
+ weixin4j-mp:新增个性化菜单接口
+ weixin4j-mp:WeixinProxy.getCustomRecord 参数变更为 Date startTime, Date endTime, Pageable pageable
* 2015-12-19
+ weixin4j-base:删除PayUtil类,接口转移到PayApi类

View File

@ -91,4 +91,8 @@
+【重要】修改PayUtil中的createPayJsRequest方法的返回值为MchPayRequest便于二次发起支付。
+【重要】添加MchPayRequest的构造函数便于二次发起支付。
+【重要】添加MchPayRequest的构造函数便于二次发起支付。
* 2015-12-19
+ 删除PayUtil类,接口转移到PayApi类

View File

@ -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;

View File

@ -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(

View File

@ -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(

View File

@ -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);
}
}

View File

@ -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());
}
}

View File

@ -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: 退款申请接口

View File

@ -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);
}
/**

View File

@ -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();
}

View File

@ -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() + "]";
}
}

View File

@ -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));
}
}

View File

@ -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&timestamp=%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(

View File

@ -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

View File

@ -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&timestamp=%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());
}
}

View File

@ -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);