新增冲正和被扫支付接口
This commit is contained in:
parent
6e70112b66
commit
f4aec9dc99
@ -70,18 +70,20 @@ weixin4j
|
||||
|
||||
+ **weixin4j-mp**: 新增获取`微信服务器IP地址`接口
|
||||
|
||||
+ **weixin4j-mp**: 解决`server工程`打包不能运行问题(`ClassUtil`无法获取jar包里面的类)
|
||||
+ **weixin4j-mp**: 解决`server工程`打包后不能运行问题(`ClassUtil`无法获取jar包里面的类)
|
||||
|
||||
+ **weixin4j-mp**: 新增被动消息的`加密`以及回复消息的`解密`
|
||||
|
||||
* 2014-11-16
|
||||
|
||||
+ **weixin4j-mp**: 新增`多客服`接口
|
||||
|
||||
* 2014-11-17
|
||||
|
||||
+ **weixin4j-mp**: 新增`冲正`和`被扫支付`接口
|
||||
|
||||
接下来
|
||||
------
|
||||
* 被扫支付
|
||||
|
||||
* 企业号API封装
|
||||
|
||||
* 微信小店
|
||||
|
||||
@ -17,10 +17,10 @@ import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
* @see
|
||||
*/
|
||||
public class ConfigUtil {
|
||||
private static ResourceBundle weixin;
|
||||
private final static ResourceBundle weixinBundle;
|
||||
static {
|
||||
weixin = ResourceBundle.getBundle("weixin");
|
||||
Set<String> keySet = weixin.keySet();
|
||||
weixinBundle = ResourceBundle.getBundle("weixin");
|
||||
Set<String> keySet = weixinBundle.keySet();
|
||||
for (String key : keySet) {
|
||||
if (!key.endsWith("_path")) {
|
||||
continue;
|
||||
@ -30,7 +30,7 @@ public class ConfigUtil {
|
||||
}
|
||||
|
||||
public static String getValue(String key) {
|
||||
return weixin.getString(key);
|
||||
return weixinBundle.getString(key);
|
||||
}
|
||||
|
||||
public static WeixinAccount getWeixinAccount() {
|
||||
|
||||
@ -72,10 +72,14 @@ weixin4j-mp
|
||||
|
||||
+ **weixin4j-mp-api**: 新增获取`微信服务器IP地址接口`
|
||||
|
||||
+ **weixin4j-mp-server**: 解决`server工程`打包不能运行问题(`ClassUtil`无法获取jar包里面的类)
|
||||
+ **weixin4j-mp-server**: 解决`server工程`打包后不能运行问题(`ClassUtil`无法获取jar包里面的类)
|
||||
|
||||
+ **weixin4j-mp-server**: 新增被动消息的`加密`以及回复消息的`解密`
|
||||
|
||||
* 2014-11-16
|
||||
|
||||
+ **weixin4j-mp-api**: 新增`多客服`接口
|
||||
+ **weixin4j-mp-api**: 新增`多客服`接口
|
||||
|
||||
* 2014-11-17
|
||||
|
||||
+ **weixin4j-mp-api**: 新增`冲正`和`被扫支付`接口
|
||||
@ -114,4 +114,8 @@ weixin.properties说明
|
||||
|
||||
* 2014-11-16
|
||||
|
||||
+ 新增`多客服`接口
|
||||
+ 新增`多客服`接口
|
||||
|
||||
* 2014-11-17
|
||||
|
||||
+ 新增`冲正`和`被扫支付`接口
|
||||
@ -36,6 +36,7 @@ import com.foxinmy.weixin4j.mp.model.User;
|
||||
import com.foxinmy.weixin4j.mp.msg.model.Article;
|
||||
import com.foxinmy.weixin4j.mp.msg.model.BaseMsg;
|
||||
import com.foxinmy.weixin4j.mp.msg.notify.BaseNotify;
|
||||
import com.foxinmy.weixin4j.mp.payment.ApiResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.Refund;
|
||||
import com.foxinmy.weixin4j.mp.payment.RefundResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.Order;
|
||||
@ -980,4 +981,39 @@ public class WeixinProxy {
|
||||
public List<String> getcallbackip() throws WeixinException {
|
||||
return helperApi.getcallbackip();
|
||||
}
|
||||
|
||||
/**
|
||||
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:支
|
||||
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
|
||||
* 如需实现相同功能请调用退款接口</font></br> <font
|
||||
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
|
||||
*
|
||||
* @param ca
|
||||
* 证书文件
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @return 撤销结果
|
||||
* @see com.foxinmy.weixin4j.mp.api.PayApi
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public ApiResult reverse(InputStream ca, IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
return payApi.reverse(ca, idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* 冲正撤销:默认采用properties中配置的ca文件
|
||||
*
|
||||
* @param idQuery
|
||||
* transaction_id、out_trade_no 二选一
|
||||
* @return 撤销结果
|
||||
* @see {@link com.foxinmy.weixin4j.mp.WeixinProxy#reverse(InputStream, IdQuery)}
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ApiResult reverse(IdQuery idQuery) throws WeixinException,
|
||||
IOException {
|
||||
return payApi.reverse(idQuery);
|
||||
}
|
||||
}
|
||||
|
||||
@ -42,6 +42,7 @@ import com.foxinmy.weixin4j.http.SSLHttpRequest;
|
||||
import com.foxinmy.weixin4j.http.XmlResult;
|
||||
import com.foxinmy.weixin4j.model.Token;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.ApiResult;
|
||||
import com.foxinmy.weixin4j.mp.payment.PayUtil;
|
||||
import com.foxinmy.weixin4j.mp.payment.Refund;
|
||||
import com.foxinmy.weixin4j.mp.payment.RefundConverter;
|
||||
@ -102,7 +103,6 @@ public class PayApi extends BaseApi {
|
||||
Map<String, String> param = new HashMap<String, String>();
|
||||
param.put("appid", weixinAccount.getAppId());
|
||||
param.put("appkey", weixinAccount.getPaySignKey());
|
||||
// 用户购买的openId
|
||||
param.put("openid", openId);
|
||||
param.put("transid", transid);
|
||||
param.put("out_trade_no", outTradeNo);
|
||||
@ -204,7 +204,7 @@ public class PayApi extends BaseApi {
|
||||
*/
|
||||
public com.foxinmy.weixin4j.mp.payment.v3.Order orderQueryV3(IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
Map<String, String> map = baseMapV3(idQuery);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
@ -216,17 +216,16 @@ public class PayApi extends BaseApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* 申请退款(请求需要双向证书)<br/>
|
||||
* 申请退款(请求需要双向证书)</br>
|
||||
* <p style="color:red">
|
||||
* 交易时间超过 1 年的订单无法提交退款; <br/>
|
||||
* 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失 败后重新提交,要采用原来的
|
||||
* out_refund_no。总退款金额不能超过用户实际支付金额。<br/>
|
||||
* 交易时间超过 1 年的订单无法提交退款; </br> 支持部分退款,部分退需要设置相同的订单号和不同的 out_refund_no。一笔退款失
|
||||
* 败后重新提交,要采用原来的 out_refund_no。总退款金额不能超过用户实际支付金额。</br>
|
||||
* </p>
|
||||
*
|
||||
* @param ca
|
||||
* 证书文件
|
||||
* @param idQuery
|
||||
* ) 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @param outRefundNo
|
||||
* 商户系统内部的退款单号,商 户系统内部唯一,同一退款单号多次请求只退一笔
|
||||
@ -341,7 +340,7 @@ public class PayApi extends BaseApi {
|
||||
SSLHttpRequest request = new SSLHttpRequest(ctx);
|
||||
response = request.get(refund_uri, map);
|
||||
} else if (version == 3) {
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
Map<String, String> map = baseMapV3(idQuery);
|
||||
map.put("out_refund_no", outRefundNo);
|
||||
map.put("total_fee", DateUtil.formaFee2Fen(totalFee));
|
||||
map.put("refund_fee", DateUtil.formaFee2Fen(refundFee));
|
||||
@ -362,9 +361,8 @@ public class PayApi extends BaseApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* 不同的退款接口选择<br/>
|
||||
* 默认采用properties中配置的ca文件<br/>
|
||||
* V2支付则需要传入opUserPasswd参数<br/>
|
||||
* 退款申请:默认采用properties中配置的ca文件</br> <font
|
||||
* color="red">V2支付则需要传入opUserPasswd参数</font>
|
||||
*
|
||||
* @see {@link com.foxinmy.weixin4j.mp.api.PayApi#refund(InputStream, IdQuery, String, double, double, String, String)}
|
||||
*/
|
||||
@ -376,6 +374,50 @@ public class PayApi extends BaseApi {
|
||||
refundFee, opUserId, opUserPasswd);
|
||||
}
|
||||
|
||||
/**
|
||||
* 冲正订单(需要证书)</br> 当支付返回失败,或收银系统超时需要取消交易,可以调用该接口</br> 接口逻辑:支
|
||||
* 付失败的关单,支付成功的撤销支付</br> <font color="red">7天以内的单可撤销,其他正常支付的单
|
||||
* 如需实现相同功能请调用退款接口</font></br> <font
|
||||
* color="red">调用扣款接口后请勿立即调用撤销,需要等待5秒以上。先调用查单接口,如果没有确切的返回,再调用撤销</font></br>
|
||||
*
|
||||
* @param ca
|
||||
* 证书文件
|
||||
* @param idQuery
|
||||
* 商户系统内部的订单号, transaction_id 、 out_trade_no 二选一,如果同时存在优先级:
|
||||
* transaction_id> out_trade_no
|
||||
* @return 撤销结果
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public ApiResult reverse(InputStream ca, IdQuery idQuery)
|
||||
throws WeixinException {
|
||||
SSLHttpRequest request = new SSLHttpRequest(weixinAccount.getMchId(),
|
||||
ca);
|
||||
String reverse_uri = getRequestUri("reverse_uri");
|
||||
Map<String, String> map = baseMapV3(idQuery);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
String param = map2xml(map);
|
||||
Response response = request.post(reverse_uri, param);
|
||||
return response.getAsObject(new TypeReference<ApiResult>() {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 冲正撤销:默认采用properties中配置的ca文件
|
||||
*
|
||||
* @param idQuery
|
||||
* transaction_id、out_trade_no 二选一
|
||||
* @return 撤销结果
|
||||
* @see {@link com.foxinmy.weixin4j.mp.api.PayApi#reverse(InputStream, IdQuery)}
|
||||
* @throws WeixinException
|
||||
* @throws IOException
|
||||
*/
|
||||
public ApiResult reverse(IdQuery idQuery) throws WeixinException,
|
||||
IOException {
|
||||
File ca = new File(ConfigUtil.getValue("ca_file"));
|
||||
return reverse(new FileInputStream(ca), idQuery);
|
||||
}
|
||||
|
||||
/**
|
||||
* native支付URL转短链接
|
||||
*
|
||||
@ -385,7 +427,7 @@ public class PayApi extends BaseApi {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public String getShorturl(String url) throws WeixinException {
|
||||
Map<String, String> map = baseMap2V3(null);
|
||||
Map<String, String> map = baseMapV3(null);
|
||||
map.put("long_url", url);
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
@ -402,8 +444,7 @@ public class PayApi extends BaseApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭订单<br/>
|
||||
* 当订单支付失败,调用关单接口后用新订单号重新发起支付,如果关单失败,返回已完
|
||||
* 关闭订单</br> 当订单支付失败,调用关单接口后用新订单号重新发起支付,如果关单失败,返回已完
|
||||
* 成支付请按正常支付处理。如果出现银行掉单,调用关单成功后,微信后台会主动发起退款。
|
||||
*
|
||||
* @param outTradeNo
|
||||
@ -413,7 +454,7 @@ public class PayApi extends BaseApi {
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public XmlResult closeOrder(String outTradeNo) throws WeixinException {
|
||||
Map<String, String> map = baseMap2V3(new IdQuery(outTradeNo,
|
||||
Map<String, String> map = baseMapV3(new IdQuery(outTradeNo,
|
||||
IdType.TRADENO));
|
||||
String sign = PayUtil.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
@ -477,7 +518,7 @@ public class PayApi extends BaseApi {
|
||||
response = request.get(downloadbill_uri, map);
|
||||
charset = Charset.forName("GBK");
|
||||
} else if (version == 3) {
|
||||
Map<String, String> map = baseMap2V3(null);
|
||||
Map<String, String> map = baseMapV3(null);
|
||||
map.put("bill_date", _billDate);
|
||||
map.put("bill_type", billType.name());
|
||||
String sign = PayUtil
|
||||
@ -508,8 +549,7 @@ public class PayApi extends BaseApi {
|
||||
}
|
||||
|
||||
/**
|
||||
* 退款查询<br/>
|
||||
* 退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态
|
||||
* 退款查询</br> 退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款 3 个工作日后重新查询退款状态
|
||||
*
|
||||
* @param idQuery
|
||||
* 单号 refund_id、out_refund_no、 out_trade_no 、 transaction_id
|
||||
@ -535,7 +575,7 @@ public class PayApi extends BaseApi {
|
||||
map.put("sign", sign.toLowerCase());
|
||||
response = request.get(refundquery_uri, map);
|
||||
} else if (version == 3) {
|
||||
Map<String, String> map = baseMap2V3(idQuery);
|
||||
Map<String, String> map = baseMapV3(idQuery);
|
||||
String sign = PayUtil
|
||||
.paysignMd5(map, weixinAccount.getPaySignKey());
|
||||
map.put("sign", sign);
|
||||
@ -550,7 +590,7 @@ public class PayApi extends BaseApi {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Map<String, String> baseMap2V3(IdQuery idQuery) {
|
||||
private Map<String, String> baseMapV3(IdQuery idQuery) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
map.put("appid", weixinAccount.getAppId());
|
||||
map.put("mch_id", weixinAccount.getMchId());
|
||||
|
||||
@ -102,3 +102,14 @@ downloadbill_v3_uri={mch_base_url}/pay/downloadbill
|
||||
refundquery_v3_uri={mch_base_url}/pay/refundquery
|
||||
# \u9000\u6b3e\u7533\u8bf7
|
||||
refund_v3_uri={mch_base_url}/secapi/pay/refund
|
||||
# \u51b2\u6b63\u64a4\u9500
|
||||
reverse_uri={mch_base_url}/secapi/pay/reverse
|
||||
# \u88ab\u626b\u652f\u4ed8
|
||||
micropay_uri={mch_base_url}/pay/micropay
|
||||
|
||||
|
||||
# \u7edf\u4e00\u8ba2\u5355\u751f\u6210
|
||||
unifiedorder_uri={mch_base_url}/pay/unifiedorder
|
||||
# native\u652f\u4ed8\u94fe\u63a5
|
||||
nativepay_v2_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s×tamp=%s&noncestr=%s
|
||||
nativepay_v3_uri=weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s
|
||||
|
||||
@ -27,6 +27,7 @@ public class ApiResult extends XmlResult {
|
||||
private String sign;// 签名 非空
|
||||
@XStreamAlias("device_info")
|
||||
private String deviceInfo;// 微信支付分配的终端设备号 可能为空
|
||||
private String recall;// 是否需要继续调用接口 Y- 需要,N-不需要
|
||||
|
||||
public ApiResult() {
|
||||
|
||||
@ -84,13 +85,18 @@ public class ApiResult extends XmlResult {
|
||||
this.deviceInfo = deviceInfo;
|
||||
}
|
||||
|
||||
public String getRecall() {
|
||||
return recall;
|
||||
}
|
||||
|
||||
public void setRecall(String recall) {
|
||||
this.recall = recall;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ApiResult [appId=" + appId + ", mchId=" + mchId + ", subMchId="
|
||||
+ subMchId + ", nonceStr=" + nonceStr + ", sign=" + sign
|
||||
+ ", deviceInfo=" + deviceInfo + ", getReturnCode()="
|
||||
+ getReturnCode() + ", getReturnMsg()=" + getReturnMsg()
|
||||
+ ", getResultCode()=" + getResultCode() + ", getErrCode()="
|
||||
+ getErrCode() + ", getErrCodeDes()=" + getErrCodeDes() + "]";
|
||||
+ ", deviceInfo=" + deviceInfo + ", recall=" + recall + "]";
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,127 @@
|
||||
package com.foxinmy.weixin4j.mp.payment;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.util.RandomUtil;
|
||||
import com.thoughtworks.xstream.annotations.XStreamAlias;
|
||||
|
||||
/**
|
||||
* 刷卡支付
|
||||
*
|
||||
* @className MicroPayPackage
|
||||
* @author jy
|
||||
* @date 2014年11月17日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
@XStreamAlias("xml")
|
||||
public class MicroPayPackage extends PayPackage {
|
||||
|
||||
private static final long serialVersionUID = 8944928173669656177L;
|
||||
|
||||
private String appid; // 微信分配的公众账号 必须
|
||||
private String mch_id; // 微信支付分配的商户号 必须
|
||||
private String device_info; // 微信支付分配的终端设备号 非必须
|
||||
private String nonce_str; // 随机字符串,不长于 32 位 必须
|
||||
private String sign; // 签名 必须
|
||||
private String auth_code; // 扫码支付授权码 ,设备读取用 户微信中的条码或者二维码 信息
|
||||
|
||||
public MicroPayPackage() {
|
||||
|
||||
}
|
||||
|
||||
public MicroPayPackage(WeixinAccount weixinAccount, String body,
|
||||
String attach, String out_trade_no, double total_fee,
|
||||
String spbill_create_ip, String auth_code) {
|
||||
this(weixinAccount.getAppId(), weixinAccount.getMchId(), weixinAccount
|
||||
.getDeviceInfo(), RandomUtil.generateString(16), body, attach,
|
||||
out_trade_no, total_fee, spbill_create_ip, null, null, null,
|
||||
auth_code);
|
||||
}
|
||||
|
||||
public MicroPayPackage(String appid, String mch_id, String device_info,
|
||||
String nonce_str, String body, String attach, String out_trade_no,
|
||||
double total_fee, String spbill_create_ip, Date time_start,
|
||||
Date time_expire, String goods_tag, String auth_code) {
|
||||
super(body, attach, out_trade_no, total_fee, spbill_create_ip,
|
||||
time_start, time_expire, goods_tag, null);
|
||||
this.appid = appid;
|
||||
this.mch_id = mch_id;
|
||||
this.device_info = device_info;
|
||||
this.nonce_str = nonce_str;
|
||||
this.auth_code = auth_code;
|
||||
}
|
||||
|
||||
public String getAppid() {
|
||||
return appid;
|
||||
}
|
||||
|
||||
public void setAppid(String appid) {
|
||||
this.appid = appid;
|
||||
}
|
||||
|
||||
public String getMch_id() {
|
||||
return mch_id;
|
||||
}
|
||||
|
||||
public void setMch_id(String mch_id) {
|
||||
this.mch_id = mch_id;
|
||||
}
|
||||
|
||||
public String getDevice_info() {
|
||||
return device_info;
|
||||
}
|
||||
|
||||
public void setDevice_info(String device_info) {
|
||||
this.device_info = device_info;
|
||||
}
|
||||
|
||||
public String getNonce_str() {
|
||||
return nonce_str;
|
||||
}
|
||||
|
||||
public void setNonce_str(String nonce_str) {
|
||||
this.nonce_str = nonce_str;
|
||||
}
|
||||
|
||||
public String getSign() {
|
||||
return sign;
|
||||
}
|
||||
|
||||
public void setSign(String sign) {
|
||||
this.sign = sign;
|
||||
}
|
||||
|
||||
public void setBody(String body) {
|
||||
super.setBody(StringUtils.isBlank(body) ? "服务费用" : body);
|
||||
}
|
||||
|
||||
public void setNotify_url(String notify_url) {
|
||||
super.setNotify_url(notify_url);
|
||||
}
|
||||
|
||||
public String getAuth_code() {
|
||||
return auth_code;
|
||||
}
|
||||
|
||||
public void setAuth_code(String auth_code) {
|
||||
this.auth_code = auth_code;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "MicroPayPackage [appid=" + appid + ", mch_id=" + mch_id
|
||||
+ ", device_info=" + device_info + ", nonce_str=" + nonce_str
|
||||
+ ", sign=" + sign + ", auth_code=" + auth_code
|
||||
+ ", getBody()=" + getBody() + ", getAttach()=" + getAttach()
|
||||
+ ", getOut_trade_no()=" + getOut_trade_no()
|
||||
+ ", getTotal_fee()=" + getTotal_fee()
|
||||
+ ", getSpbill_create_ip()=" + getSpbill_create_ip()
|
||||
+ ", getTime_start()=" + getTime_start()
|
||||
+ ", getTime_expire()=" + getTime_expire()
|
||||
+ ", getGoods_tag()=" + getGoods_tag() + "]";
|
||||
}
|
||||
}
|
||||
@ -46,9 +46,8 @@ public class PayAction {
|
||||
public JSONObject jsPay() {
|
||||
JSONObject obj = new JSONObject();
|
||||
PayPackage payPackage = null;
|
||||
// V3 支付
|
||||
// 此处的openid为微信用户的openid
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
// V3 支付
|
||||
payPackage = new PayPackageV3(weixinAccount, "用户openid", "商品描述",
|
||||
"系统内部订单号", 1d, "IP地址", TradeType.JSAPI);
|
||||
// V2 支付
|
||||
@ -58,7 +57,6 @@ public class PayAction {
|
||||
String jspay = null;
|
||||
try {
|
||||
jspay = PayUtil.createPayJsRequestJson(payPackage, weixinAccount);
|
||||
jspay = PayUtil.createPayJsRequestJson(payPackage, weixinAccount);
|
||||
} catch (PayException e) {
|
||||
log.error("create jspay error,{}", weixinAccount, e);
|
||||
}
|
||||
@ -80,7 +78,7 @@ public class PayAction {
|
||||
}
|
||||
|
||||
/**
|
||||
* JSAPI(V2)支付成功时的回调通知=<br>
|
||||
* JSAPI(V2)支付成功(前端)时的回调通知<br>
|
||||
* <xml><br/>
|
||||
* <OpenId><![CDATA[111222]]></OpenId><br/>
|
||||
* <AppId><![CDATA[wwwwb4f85f3a797777]]></AppId><br/>
|
||||
@ -105,12 +103,9 @@ public class PayAction {
|
||||
/*
|
||||
* 收集url中携带的参数 /pay/notify/back?attach=8&bank_billno=201410293351060&
|
||||
* bank_type=2032&discount=0&fee_type=1&input_charset=UTF-8&
|
||||
* notify_id=9fKbVf_qg6y-
|
||||
* wSjtSMV0PLXeEn2oGfTM1s9dWSvR2B9U6iFQRTzmjrMWKUxvh9mpBLvnh8aqFbC_OFk1pTvFnFUO00Lln4fh
|
||||
* & out_trade_no=D14102900031&partner=1221928801&product_fee=1&sign=
|
||||
* B9D6E772C271C9B86B8436FC9F5DFC1A&
|
||||
* sign_type=MD5&time_end=20141029183707
|
||||
* &total_fee=1&trade_mode=1&trade_state=0&
|
||||
* notify_id=9fKbVf_qg6y-wSjtSMV0PLXeEn2oGfTM1s9dWSvR2B9U6iFQRTzmjrMWKUxvh9mpBLvnh8aqFbC_OFk1pTvFnFUO00Lln4fh&
|
||||
* out_trade_no=D14102900031&partner=1221928801&product_fee=1&sign=B9D6E772C271C9B86B8436FC9F5DFC1A&
|
||||
* sign_type=MD5&time_end=20141029183707&total_fee=1&trade_mode=1&trade_state=0&
|
||||
* transaction_id=1221928801201410296039230054&transport_fee=0
|
||||
*/
|
||||
log.info("jspay_notify_orderinfo,{}", objMap);
|
||||
@ -142,7 +137,7 @@ public class PayAction {
|
||||
}
|
||||
|
||||
/**
|
||||
* JSAPI(V3)支付成功时的回调通知
|
||||
* JSAPI(V3)支付成功(前端)时的回调通知
|
||||
*
|
||||
*
|
||||
* @param inputStream
|
||||
@ -168,39 +163,6 @@ public class PayAction {
|
||||
return XStream.to(new XmlResult());
|
||||
}
|
||||
|
||||
/**
|
||||
* 告警通知 需要成功返回 success <br/>
|
||||
* <xml><br/>
|
||||
* <AppId><![CDATA[wxf8b4f85f3a794e77]]></AppId><br/>
|
||||
* <ErrorType>1001</ErrorType><br/>
|
||||
* <Description><![CDATA[错误描述]]></Description><br/>
|
||||
* <AlarmContent><![CDATA[错误详情]]></AlarmContent><br/>
|
||||
* <TimeStamp>1393860740</TimeStamp><br/>
|
||||
* <AppSignature><![CDATA[签名方式跟JsPayRequest中的paySign一样]]></
|
||||
* AppSignature><br/>
|
||||
* <SignMethod><![CDATA[sha1]]></SignMethod><br/>
|
||||
* </xml><br/>
|
||||
* 参与签名字段:alarmcontent、appid、appkey、description、errortype、timestamp
|
||||
*
|
||||
* @param inputStream
|
||||
* xml数据
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v2.PayWarn
|
||||
* @return
|
||||
*/
|
||||
public String warning(InputStream inputStream) {
|
||||
PayWarn payWarn = XStream.get(inputStream, PayWarn.class);
|
||||
log.info("pay_warning,{}", payWarn);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
String sign = payWarn.getPaySign();
|
||||
payWarn.setPaySign(null);
|
||||
payWarn.setSignType(null);
|
||||
// 验证微信签名
|
||||
String vaild_sign = PayUtil.paysignSha(payWarn,
|
||||
weixinAccount.getPaySignKey());
|
||||
log.info("微信签名----->sign={},vaild_sign={}", sign, vaild_sign);
|
||||
return "success";
|
||||
}
|
||||
|
||||
/**
|
||||
* V2.x版本Native支付时POST数据<br>
|
||||
* <xml><br/>
|
||||
@ -288,6 +250,39 @@ public class PayAction {
|
||||
return XStream.to(payReponse);
|
||||
}
|
||||
|
||||
/**
|
||||
* 告警通知 需要成功返回 success <br/>
|
||||
* <xml><br/>
|
||||
* <AppId><![CDATA[wxf8b4f85f3a794e77]]></AppId><br/>
|
||||
* <ErrorType>1001</ErrorType><br/>
|
||||
* <Description><![CDATA[错误描述]]></Description><br/>
|
||||
* <AlarmContent><![CDATA[错误详情]]></AlarmContent><br/>
|
||||
* <TimeStamp>1393860740</TimeStamp><br/>
|
||||
* <AppSignature><![CDATA[签名方式跟JsPayRequest中的paySign一样]]></
|
||||
* AppSignature><br/>
|
||||
* <SignMethod><![CDATA[sha1]]></SignMethod><br/>
|
||||
* </xml><br/>
|
||||
* 参与签名字段:alarmcontent、appid、appkey、description、errortype、timestamp
|
||||
*
|
||||
* @param inputStream
|
||||
* xml数据
|
||||
* @see com.foxinmy.weixin4j.mp.payment.v2.PayWarn
|
||||
* @return
|
||||
*/
|
||||
public String warning(InputStream inputStream) {
|
||||
PayWarn payWarn = XStream.get(inputStream, PayWarn.class);
|
||||
log.info("pay_warning,{}", payWarn);
|
||||
WeixinAccount weixinAccount = ConfigUtil.getWeixinAccount();
|
||||
String sign = payWarn.getPaySign();
|
||||
payWarn.setPaySign(null);
|
||||
payWarn.setSignType(null);
|
||||
// 验证微信签名
|
||||
String vaild_sign = PayUtil.paysignSha(payWarn,
|
||||
weixinAccount.getPaySignKey());
|
||||
log.info("微信签名----->sign={},vaild_sign={}", sign, vaild_sign);
|
||||
return "success";
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户维权
|
||||
*
|
||||
@ -308,8 +303,4 @@ public class PayAction {
|
||||
log.info("微信签名----->sign={},vaild_sign={}", sign, feedback.getPaySign());
|
||||
return "success";
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,24 +1,18 @@
|
||||
package com.foxinmy.weixin4j.mp.payment;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.codec.digest.DigestUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import com.foxinmy.weixin4j.exception.PayException;
|
||||
import com.foxinmy.weixin4j.exception.WeixinException;
|
||||
import com.foxinmy.weixin4j.http.HttpRequest;
|
||||
import com.foxinmy.weixin4j.http.Response;
|
||||
import com.foxinmy.weixin4j.model.WeixinAccount;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.JsPayRequestV2;
|
||||
import com.foxinmy.weixin4j.mp.payment.v2.NativePayResponseV2;
|
||||
@ -43,8 +37,8 @@ import com.foxinmy.weixin4j.xml.XStream;
|
||||
* @see
|
||||
*/
|
||||
public class PayUtil {
|
||||
|
||||
private static final String UNIFIEDORDER = "https://api.mch.weixin.qq.com/pay/unifiedorder";
|
||||
private static final String MICROPAYURL = "https://api.mch.weixin.qq.com/pay/micropay";
|
||||
private static final String NATIVEURLV2 = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&productid=%s×tamp=%s&noncestr=%s";
|
||||
private static final String NATIVEURLV3 = "weixin://wxpay/bizpayurl?sign=%s&appid=%s&mch_id=%s&product_id=%s&time_stamp=%s&nonce_str=%s";
|
||||
|
||||
@ -203,28 +197,17 @@ public class PayUtil {
|
||||
}
|
||||
|
||||
public static PrePay createPrePay(PayPackageV3 payPackage) {
|
||||
PrePay prePay = null;
|
||||
String payJsRequestXml = XStream.to(payPackage).replaceAll("__", "_");
|
||||
HttpClient client = null;
|
||||
HttpRequest request = new HttpRequest();
|
||||
try {
|
||||
client = new DefaultHttpClient();
|
||||
HttpPost post = new HttpPost(UNIFIEDORDER);
|
||||
post.setEntity(new StringEntity(payJsRequestXml,
|
||||
StandardCharsets.UTF_8));
|
||||
HttpResponse response = client.execute(post);
|
||||
StatusLine statusLine = response.getStatusLine();
|
||||
if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
|
||||
return new PrePay("-1", "网络异常[" + statusLine.getStatusCode()
|
||||
+ "," + statusLine.getReasonPhrase() + "]!");
|
||||
}
|
||||
String returnXml = EntityUtils.toString(response.getEntity(),
|
||||
StandardCharsets.UTF_8);
|
||||
return XStream.get(returnXml, PrePay.class);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} finally {
|
||||
client.getConnectionManager().shutdown();
|
||||
Response response = request.post(UNIFIEDORDER, payJsRequestXml);
|
||||
prePay = response.getAsObject(new TypeReference<PrePay>() {
|
||||
});
|
||||
} catch (WeixinException e) {
|
||||
prePay = new PrePay(e.getErrorCode(), e.getErrorMsg());
|
||||
}
|
||||
return new PrePay("-1", "request fail");
|
||||
return prePay;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -336,40 +319,55 @@ public class PayUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试js支付请求
|
||||
* 提交被扫支付
|
||||
*
|
||||
* @return
|
||||
* @param authCode
|
||||
* 扫码支付授权码 ,设备读取用 户微信中的条码或者二维码 信息
|
||||
* @param body
|
||||
* 商品描述
|
||||
* @param attach
|
||||
* 附加数据
|
||||
* @param orderNo
|
||||
* 商户内部唯一订单号
|
||||
* @param orderFee
|
||||
* 商品总额 单位元
|
||||
* @param ip
|
||||
* 订单生成的机器 IP
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 返回数据
|
||||
* @see {@link com.foxinmy.weixin4j.mp.payment.PayUtil#createMicroPay(MicroPayPackage, WeixinAccount)}
|
||||
* @throws WeixinException
|
||||
*/
|
||||
private static void createTestPayJsRequestJson() {
|
||||
// V2.xAPI支付
|
||||
PayPackageV2 payPackage = new PayPackageV2("pay_test", "1220403701",
|
||||
"D123456", 0.01, "http://182.92.74.85:8082/pay/notify",
|
||||
"192.168.1.1");
|
||||
WeixinAccount weixinAccount = new WeixinAccount("wx0d1d598c0c03c999",
|
||||
"2270e6c67cf4ff48fe2c6d7cc5a42157",
|
||||
"GATFzDwbQdbbci3QEQxX2rUBvwTrsMiZ", "1221966601",
|
||||
"6b506ef5fefba3142653a9affd2648d8");
|
||||
System.out.println(PayUtil.createPayJsRequestJsonV2(payPackage,
|
||||
weixinAccount));
|
||||
// V3.xJSAPI支付
|
||||
try {
|
||||
weixinAccount = new WeixinAccount("wx0d1d598c0c03c999",
|
||||
"2270e6c67cf4ff48fe2c6d7cc5a42157",
|
||||
"6b506ef5fefba3142653a9affd2648d8", "10020674",
|
||||
"oyFLst1bqtuTcxK-ojF8hOGtLQao");
|
||||
System.out.println(PayUtil.createPayJsRequestJsonV3(
|
||||
"oyFLst1bqtuTcxK-ojF8hOGtLQao", "测试", "T001", 1d,
|
||||
"192.0.0.1", "http://182.92.74.85:8082/pay/notify",
|
||||
weixinAccount));
|
||||
} catch (PayException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// V2.xNative支付
|
||||
System.out.println(PayUtil.createNativePayRequestV2(weixinAccount,
|
||||
payPackage));
|
||||
public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay(
|
||||
String authCode, String body, String attach, String orderNo,
|
||||
double orderFee, String ip, WeixinAccount weixinAccount)
|
||||
throws WeixinException {
|
||||
MicroPayPackage payPackage = new MicroPayPackage(weixinAccount, body,
|
||||
attach, orderNo, orderFee, ip, authCode);
|
||||
return createMicroPay(payPackage, weixinAccount);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
createTestPayJsRequestJson();
|
||||
/**
|
||||
* 提交被扫支付
|
||||
*
|
||||
* @param payPackage
|
||||
* 订单信息
|
||||
* @param weixinAccount
|
||||
* 商户信息
|
||||
* @return 返回数据
|
||||
* @throws WeixinException
|
||||
*/
|
||||
public static com.foxinmy.weixin4j.mp.payment.v3.Order createMicroPay(
|
||||
MicroPayPackage payPackage, WeixinAccount weixinAccount)
|
||||
throws WeixinException {
|
||||
String sign = paysignMd5(payPackage, weixinAccount.getPaySignKey());
|
||||
payPackage.setSign(sign);
|
||||
String para = XStream.to(payPackage).replaceAll("__", "_");
|
||||
HttpRequest request = new HttpRequest();
|
||||
Response response = request.post(MICROPAYURL, para);
|
||||
return response
|
||||
.getAsObject(new TypeReference<com.foxinmy.weixin4j.mp.payment.v3.Order>() {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -51,16 +51,14 @@ public class PayPackageV3 extends PayPackage {
|
||||
this(weixinAccount.getAppId(), weixinAccount.getMchId(), weixinAccount
|
||||
.getDeviceInfo(), RandomUtil.generateString(16), body, attach,
|
||||
out_trade_no, total_fee, spbill_create_ip, null, null, null,
|
||||
notify_url, tradeType, openId, null, weixinAccount
|
||||
.getPaySignKey());
|
||||
notify_url, tradeType, openId, null);
|
||||
}
|
||||
|
||||
public PayPackageV3(String appid, String mch_id, String device_info,
|
||||
String nonce_str, String body, String attach, String out_trade_no,
|
||||
double total_fee, String spbill_create_ip, Date time_start,
|
||||
Date time_expire, String goods_tag, String notify_url,
|
||||
TradeType tradeType, String openid, String product_id,
|
||||
String paySignKey) {
|
||||
TradeType tradeType, String openid, String product_id) {
|
||||
super(body, attach, out_trade_no, total_fee, spbill_create_ip,
|
||||
time_start, time_expire, goods_tag, notify_url);
|
||||
this.appid = appid;
|
||||
|
||||
@ -25,7 +25,6 @@ public class PrePay extends ApiResult {
|
||||
@XStreamAlias("code_url")
|
||||
private String codeUrl;// trade_type 为 NATIVE 是有 返回,此参数可直接生成二 维码展示出来进行扫码支付
|
||||
// 可能为空
|
||||
|
||||
public PrePay() {
|
||||
|
||||
}
|
||||
|
||||
@ -53,6 +53,6 @@ weixin4j-mp-server
|
||||
|
||||
* 2014-11-15
|
||||
|
||||
+ 解决`server工程`打包不能运行问题(`ClassUtil`无法获取jar包里面的类)
|
||||
+ 解决`server工程`打包后不能运行问题(`ClassUtil`无法获取jar包里面的类)
|
||||
|
||||
+ 新增被动消息的`加密`以及回复消息的`解密`
|
||||
@ -19,6 +19,14 @@ import com.foxinmy.weixin4j.mp.type.EncryptType;
|
||||
import com.foxinmy.weixin4j.mp.util.HttpUtil;
|
||||
import com.foxinmy.weixin4j.util.MessageUtil;
|
||||
|
||||
/**
|
||||
* 微信被动消息处理类
|
||||
* @className WeixinServerHandler
|
||||
* @author jy
|
||||
* @date 2014年11月16日
|
||||
* @since JDK 1.7
|
||||
* @see
|
||||
*/
|
||||
public class WeixinServerHandler extends
|
||||
SimpleChannelInboundHandler<HttpWeixinMessage> {
|
||||
|
||||
@ -83,6 +91,7 @@ public class WeixinServerHandler extends
|
||||
HttpResponse httpResponse = HttpUtil
|
||||
.createWeixinMessageResponse("");
|
||||
ctx.write(httpResponse);
|
||||
return;
|
||||
}
|
||||
if (httpMessage.getEncryptType() == EncryptType.RAW) {
|
||||
HttpResponse httpResponse = HttpUtil
|
||||
|
||||
@ -15,7 +15,7 @@ import com.foxinmy.weixin4j.mp.server.WeixinServerInitializer;
|
||||
/**
|
||||
* 微信服务netty启动程序
|
||||
*
|
||||
* @className WeixinBootstrap
|
||||
* @className WeixinServerBootstrap
|
||||
* @author jy
|
||||
* @date 2014年10月12日
|
||||
* @since JDK 1.7
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user