新增冲正被扫支付接口

This commit is contained in:
jy.hu 2014-11-17 20:57:38 +08:00
parent 6e70112b66
commit f4aec9dc99
16 changed files with 375 additions and 150 deletions

View File

@ -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封装
* 微信小店

View File

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

View File

@ -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**: 新增`冲正``被扫支付`接口

View File

@ -114,4 +114,8 @@ weixin.properties说明
* 2014-11-16
+ 新增`多客服`接口
+ 新增`多客服`接口
* 2014-11-17
+ 新增`冲正``被扫支付`接口

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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>
* &ltxml&gt<br/>
* &ltOpenId&gt&lt![CDATA[111222]]&gt&lt/OpenId&gt<br/>
* &ltAppId&gt&lt![CDATA[wwwwb4f85f3a797777]]&gt&lt/AppId&gt<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/>
* &ltxml&gt<br/>
* &ltAppId&gt&lt![CDATA[wxf8b4f85f3a794e77]]&gt&lt/AppId&gt<br/>
* &ltErrorType&gt1001&lt/ErrorType&gt<br/>
* &ltDescription&gt&lt![CDATA[错误描述]]>&lt/Description&gt<br/>
* &ltAlarmContent&gt&lt![CDATA[错误详情]]>&lt/AlarmContent&gt<br/>
* &ltTimeStamp&gt1393860740&lt/TimeStamp&gt<br/>
* &ltAppSignature&gt&lt![CDATA[签名方式跟JsPayRequest中的paySign一样]]&gt&lt/
* AppSignature&gt<br/>
* &ltSignMethod&gt&lt![CDATA[sha1]]&gt&lt/SignMethod&gt<br/>
* &lt/xml&gt<br/>
* 参与签名字段:alarmcontentappidappkeydescriptionerrortypetimestamp
*
* @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>
* &ltxml&gt<br/>
@ -288,6 +250,39 @@ public class PayAction {
return XStream.to(payReponse);
}
/**
* 告警通知 需要成功返回 success <br/>
* &ltxml&gt<br/>
* &ltAppId&gt&lt![CDATA[wxf8b4f85f3a794e77]]&gt&lt/AppId&gt<br/>
* &ltErrorType&gt1001&lt/ErrorType&gt<br/>
* &ltDescription&gt&lt![CDATA[错误描述]]>&lt/Description&gt<br/>
* &ltAlarmContent&gt&lt![CDATA[错误详情]]>&lt/AlarmContent&gt<br/>
* &ltTimeStamp&gt1393860740&lt/TimeStamp&gt<br/>
* &ltAppSignature&gt&lt![CDATA[签名方式跟JsPayRequest中的paySign一样]]&gt&lt/
* AppSignature&gt<br/>
* &ltSignMethod&gt&lt![CDATA[sha1]]&gt&lt/SignMethod&gt<br/>
* &lt/xml&gt<br/>
* 参与签名字段:alarmcontentappidappkeydescriptionerrortypetimestamp
*
* @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) {
}
}

View File

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

View File

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

View File

@ -25,7 +25,6 @@ public class PrePay extends ApiResult {
@XStreamAlias("code_url")
private String codeUrl;// trade_type NATIVE 是有 返回,此参数可直接生成二 维码展示出来进行扫码支付
// 可能为空
public PrePay() {
}

View File

@ -53,6 +53,6 @@ weixin4j-mp-server
* 2014-11-15
+ 解决`server工程`打包不能运行问题(`ClassUtil`无法获取jar包里面的类)
+ 解决`server工程`打包不能运行问题(`ClassUtil`无法获取jar包里面的类)
+ 新增被动消息的`加密`以及回复消息的`解密`

View File

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

View File

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