提交 5def62fe 编写于 作者: J jmdhappy

微信支付SDK更换为weixin-java-pay,增加微信H5支付,优化一些异常情况的处理

上级 dd9d81f9
......@@ -16,6 +16,7 @@ public class PayConstant {
public final static String PAY_CHANNEL_WX_JSAPI = "WX_JSAPI"; // 微信公众号支付
public final static String PAY_CHANNEL_WX_NATIVE = "WX_NATIVE"; // 微信原生扫码支付
public final static String PAY_CHANNEL_WX_APP = "WX_APP"; // 微信APP支付
public final static String PAY_CHANNEL_WX_MWEB = "WX_MWEB"; // 微信H5支付
public final static String PAY_CHANNEL_IAP = "IAP"; // 苹果应用内支付
public final static String PAY_CHANNEL_ALIPAY_MOBILE = "ALIPAY_MOBILE"; // 支付宝移动支付
public final static String PAY_CHANNEL_ALIPAY_PC = "ALIPAY_PC"; // 支付宝PC支付
......@@ -61,8 +62,10 @@ public class PayConstant {
public static class WxConstant {
public final static String TRADE_TYPE_APP = "APP"; // APP支付
public final static String TRADE_TYPE_JSPAI = "JSAPI"; // 公众号支付
public final static String TRADE_TYPE_JSPAI = "JSAPI"; // 公众号支付或小程序支付
public final static String TRADE_TYPE_NATIVE = "NATIVE"; // 原生扫码支付
public final static String TRADE_TYPE_MWEB = "MWEB"; // H5支付
}
public static class IapConstant {
......
......@@ -19,8 +19,8 @@ public class PayOrderDemo {
// 验签key
static final String repKey = "Hpcl522AV6q613KIi46u6g6XuW8vM1N8bFgyv769770MdYe9u37M4y7rIpl8";
static final String baseUrl = "http://api.xxpay.org/api";
//static final String baseUrl = "http://localhost:3020/api";
//static final String baseUrl = "http://api.xxpay.org/api";
static final String baseUrl = "http://localhost:3020/api";
static final String notifyUrl = "http://www.baidu.com"; // 本地环境测试,可到ngrok.cc网站注册
public static void main(String[] args) {
......@@ -32,17 +32,31 @@ public class PayOrderDemo {
JSONObject paramMap = new JSONObject();
paramMap.put("mchId", mchId); // 商户ID
paramMap.put("mchOrderNo", System.currentTimeMillis()); // 商户订单号
paramMap.put("channelId", "ALIPAY_PC"); // 支付渠道ID, WX_NATIVE,ALIPAY_WAP,ALIPAY_PC,ALIPAY_MOBILE
// 支付渠道ID, WX_NATIVE(微信扫码),WX_JSAPI(微信公众号或微信小程序),WX_APP(微信APP),WX_MWEB(微信H5),ALIPAY_WAP(支付宝手机支付),ALIPAY_PC(支付宝网站支付),ALIPAY_MOBILE(支付宝移动支付)
paramMap.put("channelId", "WX_MWEB");
paramMap.put("amount", 1); // 支付金额,单位分
paramMap.put("currency", "cny"); // 币种, cny-人民币
paramMap.put("clientIp", "114.112.124.236"); // 用户地址
paramMap.put("clientIp", "211.94.116.218"); // 用户地址,微信H5支付时要真实的
paramMap.put("device", "WEB"); // 设备
paramMap.put("subject", "XXPAY支付测试");
paramMap.put("body", "XXPAY支付测试");
paramMap.put("notifyUrl", notifyUrl); // 回调URL
paramMap.put("param1", ""); // 扩展参数1
paramMap.put("param2", ""); // 扩展参数2
paramMap.put("extra", "{\"productId\":\"120989823\",\"openId\":\"o2RvowBf7sOVJf8kJksUEMceaDqo\"}"); // 附加参数
paramMap.put("extra", "{\n" +
" \"productId\": \"120989823\",\n" +
" \"openId\": \"o2RvowBf7sOVJf8kJksUEMceaDqo\",\n" +
" \"sceneInfo\": {\n" +
" \"h5_info\": {\n" +
" \"type\": \"Wap\",\n" +
" \"wap_url\": \"http://shop.xxpay.org\",\n" +
" \"wap_name\": \"xxpay充值\"\n" +
" }\n" +
" }\n" +
"}"); // 附加参数
//{"h5_info": {"type":"Wap","wap_url": "https://pay.qq.com","wap_name": "腾讯充值"}}
String reqSign = PayDigestUtil.getSign(paramMap, reqKey);
paramMap.put("sign", reqSign); // 签名
String reqData = "params=" + paramMap.toJSONString();
......
# \u652F\u4ED8\u5B9D\u670D\u52A1\u5668\u5F02\u6B65\u901A\u77E5\u9875\u9762\u8DEF\u5F84
ali.notify_url=http://api.xxpay.org/notify/pay/aliPayNotifyRes.htm
ali.notify_url=http://xxpay.ngrok.cc/notify/pay/aliPayNotifyRes.htm
# \u652F\u4ED8\u5B9D\u9875\u9762\u8DF3\u8F6C\u540C\u6B65\u901A\u77E5\u9875\u9762\u8DEF\u5F84(\u81EA\u884C\u914D\u7F6E)
ali.return_url=http://www.xxpay.org
# \u5FAE\u4FE1\u652F\u4ED8\u56DE\u8C03\u5730\u5740
wx.notify_url=http://api.xxpay.org/notify/pay/wxPayNotifyRes.htm
wx.notify_url=http://xxpay.ngrok.cc/notify/pay/wxPayNotifyRes.htm
# \u652F\u4ED8\u8BC1\u4E66\u6839\u8DEF\u5F84
cert.root.path=/home/xxpay/service/cert
\ No newline at end of file
cert.root.path=/Users/dingzhiwei/java/tmp/cert
\ No newline at end of file
......@@ -24,22 +24,6 @@
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/webapp/WEB-INF/lib/</directory>
<targetPath>BOOT-INF/lib/</targetPath>
<includes>
<include>**/*.jar</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
<targetPath>BOOT-INF/classes/</targetPath>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
......
......@@ -53,6 +53,11 @@
<artifactId>xstream</artifactId>
<version>1.4.7</version>
</dependency>
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>2.7.7</version>
</dependency>
<!--ali_pay-->
<dependency>
<groupId>com.alipay</groupId>
......
package org.xxpay.service.channel.tencent;
public class Main {
/*public static void main(String[] args) {
try {
//--------------------------------------------------------------------
//温馨提示,第一次使用该SDK时请到com.tencent.common.Configure类里面进行配置
//--------------------------------------------------------------------
//--------------------------------------------------------------------
//PART One:基础组件测试
//--------------------------------------------------------------------
//1)https请求可用性测试
//HTTPSPostRquestWithCert.test();
//2)测试项目用到的XStream组件,本项目利用这个组件将Java对象转换成XML数据Post给API
//XStreamTest.test();
//--------------------------------------------------------------------
//PART Two:基础服务测试
//--------------------------------------------------------------------
//1)测试被扫支付API
//PayServiceTest.test();
//2)测试被扫订单查询API
//PayQueryServiceTest.test();
//3)测试撤销API
//温馨提示,测试支付API成功扣到钱之后,可以通过调用PayQueryServiceTest.test(),将支付成功返回的transaction_id和out_trade_no数据贴进去,完成撤销工作,把钱退回来 ^_^v
//ReverseServiceTest.test();
//4)测试退款申请API
//RefundServiceTest.test();
//5)测试退款查询API
//RefundQueryServiceTest.test();
//6)测试对账单API
//DownloadBillServiceTest.test();
//本地通过xml进行API数据模拟的时候,先按需手动修改xml各个节点的值,然后通过以下方法对这个新的xml数据进行签名得到一串合法的签名,最后把这串签名放到这个xml里面的sign字段里,这样进行模拟的时候就可以通过签名验证了
// Util.log(Signature.getSignFromResponseString(Util.getLocalXMLString("/test/com/tencent/business/refundqueryserviceresponsedata/refundquerysuccess2.xml")));
//Util.log(new Date().getTime());
//Util.log(System.currentTimeMillis());
} catch (Exception e){
Util.log(e.getMessage());
}
}*/
}
package org.xxpay.service.channel.tencent;
import org.xxpay.service.channel.tencent.protocol.downloadbill_protocol.DownloadBillReqData;
import org.xxpay.service.channel.tencent.protocol.pay_protocol.ScanPayReqData;
import org.xxpay.service.channel.tencent.protocol.pay_query_protocol.ScanPayQueryReqData;
import org.xxpay.service.channel.tencent.protocol.refund_protocol.RefundReqData;
import org.xxpay.service.channel.tencent.protocol.refund_query_protocol.RefundQueryReqData;
import org.xxpay.service.channel.tencent.protocol.reverse_protocol.ReverseReqData;
import org.xxpay.service.channel.tencent.service.*;
/**
* SDK总入口
*/
public class WXPay {
/**
* 初始化SDK依赖的几个关键配置
* @param key 签名算法需要用到的秘钥
* @param appID 公众账号ID
* @param mchID 商户ID
* @param sdbMchID 子商户ID,受理模式必填
* @param certLocalPath HTTP证书在服务器中的路径,用来加载证书用
* @param certPassword HTTP证书的密码,默认等于MCHID
*/
public static void initSDKConfiguration(String key,String appID,String mchID,String sdbMchID,String certLocalPath,String certPassword){
/* Configure.setKey(key);
Configure.setAppID(appID);
Configure.setMchID(mchID);
Configure.setSubMchID(sdbMchID);
Configure.setCertLocalPath(certLocalPath);
Configure.setCertPassword(certPassword);*/
}
/**
* 请求支付服务
* @param scanPayReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的数据
* @throws Exception
*/
public static String requestScanPayService(ScanPayReqData scanPayReqData) throws Exception{
return new ScanPayService().request(scanPayReqData);
}
/**
* 请求支付查询服务
* @param scanPayQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public static String requestScanPayQueryService(ScanPayQueryReqData scanPayQueryReqData) throws Exception{
return new ScanPayQueryService().request(scanPayQueryReqData);
}
/**
* 请求退款服务
* @param refundReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public static String requestRefundService(RefundReqData refundReqData) throws Exception{
return new RefundService().request(refundReqData);
}
/**
* 请求退款查询服务
* @param refundQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public static String requestRefundQueryService(RefundQueryReqData refundQueryReqData) throws Exception{
return new RefundQueryService().request(refundQueryReqData);
}
/**
* 请求撤销服务
* @param reverseReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public static String requestReverseService(ReverseReqData reverseReqData) throws Exception{
return new ReverseService().request(reverseReqData);
}
/**
* 请求对账单下载服务
* @param downloadBillReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public static String requestDownloadBillService(DownloadBillReqData downloadBillReqData) throws Exception{
return new DownloadBillService().request(downloadBillReqData);
}
/*
*/
/**
* 直接执行被扫支付业务逻辑(包含最佳实践流程)
* @param scanPayReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件,并做好合理的响应处理
* @throws Exception
*//*
public static void doScanPayBusiness(ScanPayReqData scanPayReqData, ScanPayBusiness.ResultListener resultListener) throws Exception {
//new ScanPayBusiness().run(scanPayReqData, resultListener);
}
*/
/**
* 调用退款业务逻辑
* @param refundReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 业务逻辑可能走到的结果分支,需要商户处理
* @throws Exception
*//*
public static void doRefundBusiness(RefundReqData refundReqData, RefundBusiness.ResultListener resultListener) throws Exception {
//new RefundBusiness().run(refundReqData,resultListener);
}
*/
/**
* 运行退款查询的业务逻辑
* @param refundQueryReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件,并做好合理的响应处理
* @throws Exception
*//*
public static void doRefundQueryBusiness(RefundQueryReqData refundQueryReqData, RefundQueryBusiness.ResultListener resultListener) throws Exception {
//new RefundQueryBusiness().run(refundQueryReqData,resultListener);
}
*/
/**
* 请求对账单下载服务
* @param downloadBillReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @param resultListener 商户需要自己监听被扫支付业务逻辑可能触发的各种分支事件,并做好合理的响应处理
* @return API返回的XML数据
* @throws Exception
*//*
public static void doDownloadBillBusiness(DownloadBillReqData downloadBillReqData, DownloadBillBusiness.ResultListener resultListener) throws Exception {
//new DownloadBillBusiness().run(downloadBillReqData,resultListener);
}
*/
}
package org.xxpay.service.channel.tencent.bridge;
/**
* User: rizenguo
* Date: 2014/12/1
* Time: 17:11
*/
public interface IBridge {
/**
* 获取auth_code,这个是扫码终端设备从用户手机上扫取到的支付授权号,这个号是跟用户用来支付的银行卡绑定的,有效期是1分钟
* @return 授权码
*/
public String getAuthCode();
/**
* 获取out_trade_no,这个是商户系统内自己可以用来唯一标识该笔订单的字符串,可以包含字母和数字,不超过32位
* @return 订单号
*/
public String getOutTradeNo();
/**
* 获取body:要支付的商品的描述信息,用户会在支付成功页面里看到这个信息
* @return 描述信息
*/
public String getBody();
/**
* 获取attach:支付订单里面可以填的附加数据,API会将提交的这个附加数据原样返回,有助于商户自己可以注明该笔消费的具体内容,方便后续的运营和记录
* @return 附加数据
*/
public String getAttach();
/**
* 获取订单总额
* @return 订单总额
*/
public int getTotalFee();
/**
* 获取device_info:商户自己定义的扫码支付终端设备号,方便追溯这笔交易发生在哪台终端设备上
* @return 支付终端设备号
*/
public String getDeviceInfo();
/**
* 获取机器的ip地址
* @return 机器设备的ip地址
*/
public String getUserIp();
/**
* 获取spBillCreateIP:订单生成的机器IP
* @return 订单生成的机器IP
*/
public String getSpBillCreateIP();
/**
* 获取time_start:订单生成时间
* @return 订单生成时间
*/
public String getTimeStart();
/**
* 获取time_end:订单生成时间
* @return 订单失效时间
*/
public String getTimeExpire();
/**
* 获取goods_tag:商品标记,微信平台配置的商品标记,用于优惠券或者满减使用
* @return 商品标记
*/
public String getGoodsTag();
/**
* 获取transaction_id:微信平台支付成功时给分配的唯一交易号,一般只要有这个tracnsacion_id,后续的查询、撤销、退款都建议优先用这个,而不是商户自己的那个out_trade_no
* @return 微信平台官方分配的交易号
*/
public String getTransactionID();
/**
* 获取out_refund_no:商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
* @return 商户系统内部的退款单号
*/
public String getOutRefundNo();
/**
* 获取refund_fee:获取本次退款请求所要退的具体金额,这个金额不能比这个订单的total_fee(总金额)还大
* @return 本次退款请求所要退的具体金额
*/
public int getRefundFee();
/**
* 获取refund_id:微信平台退款成功时给分配的唯一退款号,一般只要有这个refund_id,后续的查询建议优先用这个
* @return 微信平台官方分配的退款号
*/
public String getRefundID();
/**
* 获取bill_date:获取对账单API需要的日期,格式是yyyyMMdd
* @return 要查询对账单的日期
*/
public String getBillDate();
/**
* 获取bill_type:获取对账单API需要的数据类型,这些类型在DownloadBillService里面有定义
* @return 要查询对账单的类型
*/
public String getBillType();
/**
* 获取操作员的ID,默认等于商户号
* @return 返回操作员的ID
*/
public String getOpUserID();
/**
* 获取退款货币类型,符合ISO 4217标准的三位字母代码,默认为CNY(人民币)
* @return 获取退款货币类型
*/
public String getRefundFeeType();
}
package org.xxpay.service.channel.tencent.common;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.xxpay.common.util.IPUtility;
import org.xxpay.common.util.MyLog;
import java.io.File;
import java.util.Date;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 14:40
* 这里放置各种配置数据
*/
@RefreshScope
@Service
public class Configure {
private static final MyLog _log = MyLog.getLog(Configure.class);
public Configure init(String configParam) {
JSONObject paramObj = JSON.parseObject(configParam);
this.setMchID(paramObj.getString("mchId"));
this.setAppID(paramObj.getString("appId"));
this.setCertLocalPath(certRootPath + File.separator + paramObj.getString("certLocalPath"));
this.setCertPassword(paramObj.getString("certPassword"));
this.setKey(paramObj.getString("key"));
this.setIp(IPUtility.getLocalIP());
return this;
}
// 这个就是自己要保管好的私有Key了(切记只能放在自己的后台代码里,不能放在任何可能被看到源代码的客户端程序中)
// 每次自己Post数据给API的时候都要用这个key来对所有字段进行签名,生成的签名会放在Sign这个字段,API收到Post数据的时候也会用同样的签名算法对Post过来的数据进行签名和验证
// 收到API的返回的时候也要用这个key来对返回的数据算下签名,跟API的Sign数据进行比较,如果值不一致,有可能数据被第三方给篡改
private String key;
//微信分配的公众号ID(开通公众号之后可以获取到)
private String appID;
private String mchID;
//HTTPS证书的本地路径
// private static String certLocalPath = "/Users/dingzhiwei/java/tmp/wx.crt.p12";
private String certLocalPath;
//HTTPS证书密码,默认密码等于商户号MCHID
private String certPassword;
//是否使用异步线程的方式来上报API测速,默认为异步模式
private static boolean useThreadToDoReport = true;
//配置描述
private String desc;
//机器IP
private String ip;
@Value("${cert.root.path}")
private String certRootPath;
//以下是几个API的路径:
//1)被扫支付API
public static String PAY_API = "https://api.mch.weixin.qq.com/pay/micropay";
//2)被扫支付查询API
public static String ORDER_QUERY_API = "https://api.mch.weixin.qq.com/pay/orderquery";
//3)退款API
public static String REFUND_API = "https://api.mch.weixin.qq.com/secapi/pay/refund";
//4)退款查询API
public static String REFUND_QUERY_API = "https://api.mch.weixin.qq.com/pay/refundquery";
//5)撤销API
public static String REVERSE_API = "https://api.mch.weixin.qq.com/secapi/pay/reverse";
//6)下载对账单API
public static String DOWNLOAD_BILL_API = "https://api.mch.weixin.qq.com/pay/downloadbill";
//7) 统计上报API
public static String REPORT_API = "https://api.mch.weixin.qq.com/payitil/report";
//8) 统一下单API
public static String UNIFIED_ORDER_API = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//9) 发送现金红包API
public static String SEND_REDPACK_API = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
//10) 查询现金红包API
public static String QUERY_REDPACK_API = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo";
//9) 企业付款API
public static String TRANSFERS_API = "https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers";
//10) 查询企业付款API
public static String GET_TRANSFERS_API = "https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo";
@Value("${wx.notify_url}")
private String notify_url;
// 配置加载时间
private Long loadTime = new Date().getTime();
public static boolean isUseThreadToDoReport() {
return useThreadToDoReport;
}
public static void setUseThreadToDoReport(boolean useThreadToDoReport) {
Configure.useThreadToDoReport = useThreadToDoReport;
}
public static String HttpsRequestClassName = "org.xxpay.service.channel.tencent.common.HttpsRequest";
public static void setHttpsRequestClassName(String name){
HttpsRequestClassName = name;
}
public String getAppID() {
return appID;
}
public void setAppID(String appID) {
this.appID = appID;
}
public String getCertLocalPath() {
return certLocalPath;
}
public void setCertLocalPath(String certLocalPath) {
this.certLocalPath = certLocalPath;
}
public String getCertPassword() {
return certPassword;
}
public void setCertPassword(String certPassword) {
this.certPassword = certPassword;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getKey() {
return key;
}
public void setKey(String key) {
this.key = key;
}
public String getMchID() {
return mchID;
}
public void setMchID(String mchID) {
this.mchID = mchID;
}
public String getDesc() {
return desc;
}
public String getNotify_url() {
return notify_url;
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
public void setDesc(String desc) {
this.desc = desc;
}
public Long getLoadTime() {
return loadTime;
}
public void setLoadTime(Long loadTime) {
this.loadTime = loadTime;
}
@Override
public String toString() {
return "Configure{" +
"key='" + key + '\'' +
", appID='" + appID + '\'' +
", certLocalPath='" + certLocalPath + '\'' +
", certPassword='" + certPassword + '\'' +
", desc='" + desc + '\'' +
", ip='" + ip + '\'' +
", loadTime=" + loadTime +
'}';
}
}
package org.xxpay.service.channel.tencent.common;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import org.xxpay.service.channel.tencent.service.IServiceRequest;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.ConnectionPoolTimeoutException;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLContexts;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.SocketTimeoutException;
import java.security.*;
import java.security.cert.CertificateException;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 14:36
*/
public class HttpsRequest implements IServiceRequest {
public interface ResultListener {
public void onConnectionPoolTimeoutError();
}
private static Log log = new Log(LoggerFactory.getLogger(HttpsRequest.class));
//表示请求器是否已经做了初始化工作
private boolean hasInit = false;
//连接超时时间,默认10秒
private int socketTimeout = 10000;
//传输超时时间,默认30秒
private int connectTimeout = 30000;
//请求器的配置
private RequestConfig requestConfig;
//HTTP请求器
private CloseableHttpClient httpClient;
private String crtPath;
private String crtPwd;
public HttpsRequest() throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, IOException {
//init();
}
public void init() throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
KeyStore keyStore = KeyStore.getInstance("PKCS12");
FileInputStream instream = new FileInputStream(new File(crtPath));//加载本地的证书进行https加密传输
try {
keyStore.load(instream, crtPwd.toCharArray());//设置证书密码
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} finally {
instream.close();
}
// Trust own CA and all self-signed certs
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, crtPwd.toCharArray())
.build();
// Allow TLSv1 protocol only
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[]{"TLSv1"},
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
httpClient = HttpClients.custom()
.setSSLSocketFactory(sslsf)
.build();
//根据默认超时限制初始化requestConfig
requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
hasInit = true;
}
/**
* 通过Https往API post xml数据
*
* @param url API地址
* @param xmlObj 要提交的XML数据对象
* @return API回包的实际数据
* @throws IOException
* @throws KeyStoreException
* @throws UnrecoverableKeyException
* @throws NoSuchAlgorithmException
* @throws KeyManagementException
*/
public String sendPost(String url, Object xmlObj) throws IOException, KeyStoreException, UnrecoverableKeyException, NoSuchAlgorithmException, KeyManagementException {
if (!hasInit) {
init();
}
String result = null;
HttpPost httpPost = new HttpPost(url);
//解决XStream对出现双下划线的bug
XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
//将要提交给API的数据对象转换成XML格式数据Post给API
String postDataXML = xStreamForRequestPostData.toXML(xmlObj);
Util.log("API,POST过去的数据是:");
Util.log(postDataXML);
//得指明使用UTF-8编码,否则到API服务器XML的中文不能被成功识别
StringEntity postEntity = new StringEntity(postDataXML, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(postEntity);
//设置请求器的配置
httpPost.setConfig(requestConfig);
Util.log("executing request" + httpPost.getRequestLine());
try {
HttpResponse response = httpClient.execute(httpPost);
HttpEntity entity = response.getEntity();
result = EntityUtils.toString(entity, "UTF-8");
} catch (ConnectionPoolTimeoutException e) {
log.e("http get throw ConnectionPoolTimeoutException(wait time out)");
} catch (ConnectTimeoutException e) {
log.e("http get throw ConnectTimeoutException");
} catch (SocketTimeoutException e) {
log.e("http get throw SocketTimeoutException");
} catch (Exception e) {
log.e("http get throw Exception");
} finally {
httpPost.abort();
}
return result;
}
/**
* 设置连接超时时间
*
* @param socketTimeout 连接时长,默认10秒
*/
public void setSocketTimeout(int socketTimeout) {
socketTimeout = socketTimeout;
resetRequestConfig();
}
/**
* 设置传输超时时间
*
* @param connectTimeout 传输时长,默认30秒
*/
public void setConnectTimeout(int connectTimeout) {
connectTimeout = connectTimeout;
resetRequestConfig();
}
private void resetRequestConfig(){
requestConfig = RequestConfig.custom().setSocketTimeout(socketTimeout).setConnectTimeout(connectTimeout).build();
}
/**
* 允许商户自己做更高级更复杂的请求器配置
*
* @param requestConfig 设置HttpsRequest的请求器配置
*/
public void setRequestConfig(RequestConfig requestConfig) {
requestConfig = requestConfig;
}
public void setCrt(Configure configure) {
this.crtPath = configure.getCertLocalPath();
this.crtPwd = configure.getCertPassword();
}
}
package org.xxpay.service.channel.tencent.common;
import org.slf4j.Logger;
/**
* User: rizenguo
* Date: 2014/11/12
* Time: 14:32
*/
public class Log {
public static final String LOG_TYPE_TRACE = "logTypeTrace";
public static final String LOG_TYPE_DEBUG = "logTypeDebug";
public static final String LOG_TYPE_INFO = "logTypeInfo";
public static final String LOG_TYPE_WARN = "logTypeWarn";
public static final String LOG_TYPE_ERROR = "logTypeError";
//打印日志
private Logger logger;
public Log(Logger log){
logger = log;
}
public void t(String s){
logger.trace(s);
}
public void d(String s){
logger.debug(s);
}
public void i(String s){
logger.info(s);
}
public void w(String s){
logger.warn(s);
}
public void e(String s){
logger.error(s);
}
public void log(String type,String s){
if(type.equals(Log.LOG_TYPE_TRACE)){
t(s);
}else if(type.equals(Log.LOG_TYPE_DEBUG)){
d(s);
}else if(type.equals(Log.LOG_TYPE_INFO)){
i(s);
}else if(type.equals(Log.LOG_TYPE_WARN)){
w(s);
}else if(type.equals(Log.LOG_TYPE_ERROR)){
e(s);
}
}
}
package org.xxpay.service.channel.tencent.common;
import java.security.MessageDigest;
/**
* User: rizenguo
* Date: 2014/10/23
* Time: 15:43
*/
public class MD5 {
private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5", "6", "7",
"8", "9", "a", "b", "c", "d", "e", "f"};
/**
* 转换字节数组为16进制字串
* @param b 字节数组
* @return 16进制字串
*/
public static String byteArrayToHexString(byte[] b) {
StringBuilder resultSb = new StringBuilder();
for (byte aB : b) {
resultSb.append(byteToHexString(aB));
}
return resultSb.toString();
}
/**
* 转换byte到16进制
* @param b 要转换的byte
* @return 16进制格式
*/
private static String byteToHexString(byte b) {
int n = b;
if (n < 0) {
n = 256 + n;
}
int d1 = n / 16;
int d2 = n % 16;
return hexDigits[d1] + hexDigits[d2];
}
/**
* MD5编码
* @param origin 原始字符串
* @return 经过MD5加密之后的结果
*/
public static String MD5Encode(String origin) {
String resultString = null;
try {
resultString = origin;
MessageDigest md = MessageDigest.getInstance("MD5");
resultString = byteArrayToHexString(md.digest(resultString.getBytes()));
} catch (Exception e) {
e.printStackTrace();
}
return resultString;
}
}
package org.xxpay.service.channel.tencent.common;
import java.util.Random;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 14:18
*/
public class RandomStringGenerator {
/**
* 获取一定长度的随机字符串
* @param length 指定字符串长度
* @return 一定长度的字符串
*/
public static String getRandomStringByLength(int length) {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
}
package org.xxpay.service.channel.tencent.common;
import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 15:23
*/
public class Signature {
/**
* 签名算法
* @param o 要参与签名的数据对象
* @return 签名
* @throws IllegalAccessException
*/
public static String getSign(Object o, String key) throws IllegalAccessException {
ArrayList<String> list = new ArrayList<String>();
Class cls = o.getClass();
Field[] fields = cls.getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
if (f.get(o) != null && f.get(o) != "") {
list.add(f.getName() + "=" + f.get(o) + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
result += "key=" + key;
Util.log("Sign Before MD5:" + result);
result = MD5.MD5Encode(result).toUpperCase();
Util.log("Sign Result:" + result);
return result;
}
public static String getSign(Map<String,Object> map, String key){
ArrayList<String> list = new ArrayList<String>();
for(Map.Entry<String,Object> entry:map.entrySet()){
if(!"".equals(entry.getValue())){
list.add(entry.getKey() + "=" + entry.getValue() + "&");
}
}
int size = list.size();
String [] arrayToSort = list.toArray(new String[size]);
Arrays.sort(arrayToSort, String.CASE_INSENSITIVE_ORDER);
StringBuilder sb = new StringBuilder();
for(int i = 0; i < size; i ++) {
sb.append(arrayToSort[i]);
}
String result = sb.toString();
result += "key=" + key;
//Util.log("Sign Before MD5:" + result);
result = MD5.MD5Encode(result).toUpperCase();
//Util.log("Sign Result:" + result);
return result;
}
/**
* 从API返回的XML数据里面重新计算一次签名
* @param responseString API返回的XML数据
* @return 新鲜出炉的签名
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
public static String getSignFromResponseString(String responseString, String key) throws IOException, SAXException, ParserConfigurationException {
Map<String,Object> map = XMLParser.getMapFromXML(responseString);
//清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名
map.put("sign","");
//将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
return Signature.getSign(map, key);
}
/**
* 检验API返回的数据里面的签名是否合法,避免数据在传输的过程中被第三方篡改
* @param responseString API返回的XML数据字符串
* @return API签名是否合法
* @throws ParserConfigurationException
* @throws IOException
* @throws SAXException
*/
public static boolean checkIsSignValidFromResponseString(String responseString, String key) throws ParserConfigurationException, IOException, SAXException {
Map<String,Object> map = XMLParser.getMapFromXML(responseString);
Util.log(map.toString());
String signFromAPIResponse = map.get("sign").toString();
if(signFromAPIResponse=="" || signFromAPIResponse == null){
Util.log("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
return false;
}
Util.log("服务器回包里面的签名是:" + signFromAPIResponse);
//清掉返回数据对象里面的Sign数据(不能把这个数据也加进去进行签名),然后用签名算法进行签名
map.put("sign","");
//将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
String signForAPIResponse = Signature.getSign(map, key);
if(!signForAPIResponse.equals(signFromAPIResponse)){
//签名验不过,表示这个API返回的数据有可能已经被篡改了
Util.log("API返回的数据签名验证不通过,有可能被第三方篡改!!!");
return false;
}
Util.log("恭喜,API返回的数据签名验证通过!!!");
return true;
}
}
package org.xxpay.service.channel.tencent.common;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
import com.thoughtworks.xstream.io.xml.XmlFriendlyNameCoder;
import org.slf4j.LoggerFactory;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/10/23
* Time: 14:59
*/
public class Util {
//打log用
private static Log logger = new Log(LoggerFactory.getLogger(Util.class));
/**
* 通过反射的方式遍历对象的属性和属性值,方便调试
*
* @param o 要遍历的对象
* @throws Exception
*/
public static void reflect(Object o) throws Exception {
Class cls = o.getClass();
Field[] fields = cls.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field f = fields[i];
f.setAccessible(true);
Util.log(f.getName() + " -> " + f.get(o));
}
}
public static byte[] readInput(InputStream in) throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[1024];
while ((len = in.read(buffer)) > 0) {
out.write(buffer, 0, len);
}
out.close();
in.close();
return out.toByteArray();
}
public static String inputStreamToString(InputStream is) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int i;
while ((i = is.read()) != -1) {
baos.write(i);
}
return baos.toString();
}
public static InputStream getStringStream(String sInputString) {
ByteArrayInputStream tInputStringStream = null;
if (sInputString != null && !sInputString.trim().equals("")) {
tInputStringStream = new ByteArrayInputStream(sInputString.getBytes());
}
return tInputStringStream;
}
public static Object getObjectFromXML(String xml, Class tClass) {
//将从API返回的XML数据映射到Java对象
XStream xStreamForResponseData = new XStream();
xStreamForResponseData.alias("xml", tClass);
xStreamForResponseData.ignoreUnknownElements();//暂时忽略掉一些新增的字段
return xStreamForResponseData.fromXML(xml);
}
public static String getStringFromMap(Map<String, Object> map, String key, String defaultValue) {
if (key == "" || key == null) {
return defaultValue;
}
String result = (String) map.get(key);
if (result == null) {
return defaultValue;
} else {
return result;
}
}
public static int getIntFromMap(Map<String, Object> map, String key) {
if (key == "" || key == null) {
return 0;
}
if (map.get(key) == null) {
return 0;
}
return Integer.parseInt((String) map.get(key));
}
/**
* 打log接口
* @param log 要打印的log字符串
* @return 返回log
*/
public static String log(Object log){
logger.i(log.toString());
//System.out.println(log);
return log.toString();
}
/**
* 读取本地的xml数据,一般用来自测用
* @param localPath 本地xml文件路径
* @return 读到的xml字符串
*/
public static String getLocalXMLString(String localPath) throws IOException {
return Util.inputStreamToString(Util.class.getResourceAsStream(localPath));
}
public static String objectToXML(Object o){
//解决XStream对出现双下划线的bug
XStream xStreamForRequestPostData = new XStream(new DomDriver("UTF-8", new XmlFriendlyNameCoder("-_", "_")));
//将要提交给API的数据对象转换成XML格式数据Post给API
return xStreamForRequestPostData.toXML(o);
}
}
package org.xxpay.service.channel.tencent.common;
import org.xxpay.service.channel.tencent.protocol.refund_query_protocol.RefundOrderData;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/11/1
* Time: 14:06
*/
public class XMLParser {
/**
* 从RefunQueryResponseString里面解析出退款订单数据
* @param refundQueryResponseString RefundQuery API返回的数据
* @return 因为订单数据有可能是多个,所以返回一个列表
*/
public static List<RefundOrderData> getRefundOrderList(String refundQueryResponseString) throws IOException, SAXException, ParserConfigurationException {
List list = new ArrayList();
Map<String,Object> map = XMLParser.getMapFromXML(refundQueryResponseString);
int count = Integer.parseInt((String) map.get("refund_count"));
Util.log("count:" + count);
if(count<1){
return list;
}
RefundOrderData refundOrderData;
for(int i=0;i<count;i++){
refundOrderData = new RefundOrderData();
refundOrderData.setOutRefundNo(Util.getStringFromMap(map,"out_refund_no_" + i,""));
refundOrderData.setRefundID(Util.getStringFromMap(map,"refund_id_" + i,""));
refundOrderData.setRefundChannel(Util.getStringFromMap(map,"refund_channel_" + i,""));
refundOrderData.setRefundFee(Util.getIntFromMap(map,"refund_fee_" + i));
refundOrderData.setCouponRefundFee(Util.getIntFromMap(map,"coupon_refund_fee_" + i));
refundOrderData.setRefundStatus(Util.getStringFromMap(map,"refund_status_" + i,""));
list.add(refundOrderData);
}
return list;
}
public static Map<String,Object> getMapFromXML(String xmlString) throws ParserConfigurationException, IOException, SAXException {
//这里用Dom的方式解析回包的最主要目的是防止API新增回包字段
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
InputStream is = Util.getStringStream(xmlString);
Document document = builder.parse(is);
//获取到document里面的全部结点
NodeList allNodes = document.getFirstChild().getChildNodes();
Node node;
Map<String, Object> map = new HashMap<String, Object>();
int i=0;
while (i < allNodes.getLength()) {
node = allNodes.item(i);
if(node instanceof Element){
map.put(node.getNodeName(),node.getTextContent());
}
i++;
}
return map;
}
}
package org.xxpay.service.channel.tencent.common.report;
import org.xxpay.service.channel.tencent.common.report.service.ReportService;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
/**
* User: rizenguo
* Date: 2014/12/3
* Time: 16:34
*/
public class ReportRunable implements Runnable {
private ReportService reportService ;
ReportRunable(ReportService rs){
reportService = rs;
}
@Override
public void run() {
try {
reportService.request();
} catch (UnrecoverableKeyException e) {
e.printStackTrace();
} catch (KeyManagementException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
package org.xxpay.service.channel.tencent.common.report;
import org.xxpay.service.channel.tencent.common.report.protocol.ReportReqData;
import org.xxpay.service.channel.tencent.common.report.service.ReportService;
/**
* User: rizenguo
* Date: 2014/12/3
* Time: 11:42
*/
public class Reporter {
private ReportRunable r;
private Thread t;
private ReportService rs;
/**
* 请求统计上报API
* @param reportReqData 这个数据对象里面包含了API要求提交的各种数据字段
*/
public Reporter(ReportReqData reportReqData){
rs = new ReportService(reportReqData);
}
public void run(){
r = new ReportRunable(rs);
t = new Thread(r);
t.setDaemon(true); //后台线程
t.start();
}
}
package org.xxpay.service.channel.tencent.common.report;
import org.xxpay.service.channel.tencent.common.report.protocol.ReportReqData;
/**
* User: rizenguo
* Date: 2014/12/3
* Time: 17:44
*/
public class ReporterFactory {
/**
* 请求统计上报API
* @param reportReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return 返回一个Reporter
*/
public static Reporter getReporter(ReportReqData reportReqData){
return new Reporter(reportReqData);
}
}
package org.xxpay.service.channel.tencent.common.report.protocol;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/11/12
* Time: 17:05
*/
public class ReportReqData {
//每个字段具体的意思请查看API文档
private String appid;
private String mch_id;
private String sub_mch_id;
private String device_info;
private String nonce_str;
private String sign;
//上报对应的接口的完整URL,类似:https://api.mch.weixin.qq.com/pay/unifiedorder
private String interface_url;
//接口耗时情况,单位为毫秒
private int execute_time_cost;
//发起接口调用时的机器IP
private String user_ip;
//上报该统计请求时的系统时间,格式为yyyyMMddHHmmss
private String time;
//以下是API接口返回的对应数据
private String return_code;
private String return_msg;
private String result_code;
private String err_code;
private String err_code_des;
private String out_trade_no;
/**
* 请求统计上报API
* @param deviceInfo 微信支付分配的终端设备号,商户自定义
* @param interfaceUrl 上报对应的接口的完整URL,类似: https://api.mch.weixin.qq.com/pay/unifiedorder
* @param executeTimeCost 接口耗时情况,单位为毫秒
* @param returnCode API返回的对应字段
* @param returnMsg API返回的对应字段
* @param resultCode API返回的对应字段
* @param errCode API返回的对应字段
* @param errCodeDes API返回的对应字段
* @param outTradeNo API返回的对应字段
* @param userIp 发起接口调用时的机器IP
*/
public ReportReqData(Configure configure, String deviceInfo, String interfaceUrl, int executeTimeCost, String returnCode, String returnMsg, String resultCode, String errCode, String errCodeDes, String outTradeNo, String userIp){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
//商户系统自己生成的唯一的订单号
setOut_trade_no(outTradeNo);
setDevice_info(deviceInfo);
setInterface_url(interfaceUrl);
setExecute_time_cost(executeTimeCost);
setReturn_code(returnCode);
setReturn_msg(returnMsg);
setResult_code(resultCode);
setErr_code(errCode);
setErr_code_des(errCodeDes);
setUser_ip(userIp);
setTime(getTime());
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 String getInterface_url() {
return interface_url;
}
public void setInterface_url(String interface_url) {
this.interface_url = interface_url;
}
public int getExecute_time_cost() {
return execute_time_cost;
}
public void setExecute_time_cost(int execute_time) {
this.execute_time_cost = execute_time;
}
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getUser_ip() {
return user_ip;
}
public void setUser_ip(String user_ip) {
this.user_ip = user_ip;
}
public String getTime() {
return time;
}
public void setTime(String time) {
this.time = time;
}
public Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.common.report.protocol;
/**
* User: rizenguo
* Date: 2014/11/12
* Time: 17:06
*/
public class ReportResData {
//以下是API接口返回的对应数据
private String return_code;
private String return_msg;
private String result_code;
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
}
package org.xxpay.service.channel.tencent.common.report.service;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.HttpsRequest;
import org.xxpay.service.channel.tencent.common.Util;
import org.xxpay.service.channel.tencent.common.report.protocol.ReportReqData;
import org.springframework.stereotype.Service;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* User: rizenguo
* Date: 2014/11/12
* Time: 17:07
*/
@Service
public class ReportService {
private ReportReqData reqData ;
/**
* 请求统计上报API
* @param reportReqData 这个数据对象里面包含了API要求提交的各种数据字段
*/
public ReportService(ReportReqData reportReqData){
reqData = reportReqData;
}
public ReportService(){
}
public String request() throws UnrecoverableKeyException, KeyManagementException, NoSuchAlgorithmException, KeyStoreException, IOException {
String responseString = new HttpsRequest().sendPost(Configure.REPORT_API, reqData);
Util.log(" report返回的数据:" + responseString);
return responseString;
}
/**
* 请求统计上报API
* @param reportReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的数据
* @throws Exception
*/
public static String request(ReportReqData reportReqData) throws Exception {
//--------------------------------------------------------------------
//发送HTTPS的Post请求到API地址
//--------------------------------------------------------------------
String responseString = new HttpsRequest().sendPost(Configure.REPORT_API, reportReqData);
Util.log("report返回的数据:" + responseString);
return responseString;
}
/**
* 获取time:统计发送时间,格式为yyyyMMddHHmmss,如2009年12 月25 日9 点10 分10 秒表示为20091225091010。时区为GMT+8 beijing。
* @return 订单生成时间
*/
private static String getTime(){
//订单生成时间自然就是当前服务器系统时间咯
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
return simpleDateFormat.format(new Date());
}
}
package org.xxpay.service.channel.tencent.protocol.downloadbill_protocol;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 16:48
*/
public class DownloadBillReqData {
//每个字段具体的意思请查看API文档
private String appid = "";
private String mch_id = "";
private String device_info = "";
private String nonce_str = "";
private String sign = "";
private String bill_date = "";
private String bill_type = "";
/**
* 请求对账单下载服务
* @param deviceInfo 商户自己定义的扫码支付终端设备号,方便追溯这笔交易发生在哪台终端设备上
* @param billDate 下载对账单的日期,格式:yyyyMMdd 例如:20140603
* @param billType 账单类型
* ALL,返回当日所有订单信息,默认值
SUCCESS,返回当日成功支付的订单
REFUND,返回当日退款订单
REVOKED,已撤销的订单
*/
public DownloadBillReqData(Configure configure, String deviceInfo, String billDate, String billType){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
//商户自己定义的扫码支付终端设备号,方便追溯这笔交易发生在哪台终端设备上
setDevice_info(deviceInfo);
setBill_date(billDate);
setBill_type(billType);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 String getBill_date() {
return bill_date;
}
public void setBill_date(String bill_date) {
this.bill_date = bill_date;
}
public String getBill_type() {
return bill_type;
}
public void setBill_type(String bill_type) {
this.bill_type = bill_type;
}
public Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.downloadbill_protocol;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 16:48
*/
public class DownloadBillResData {
//协议层
private String return_code = "";
private String return_msg = "";
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
}
package org.xxpay.service.channel.tencent.protocol.notify_protocol;
/**
* User: dingzhiwei
* Date: 2016/05/13
* Time: 15:03
*/
import java.io.Serializable;
/**
* 统一下单通知请求数据
*/
public class NotifyUnifiedOrderReqData implements Serializable {
private static final long serialVersionUID = -6165278068603647287L;
//协议层
private String return_code; // 返回状态码
private String return_msg; // 返回信息
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String appid; // 应用APPID
private String mch_id; // 商户号
private String device_info; // 设备号
private String nonce_str; // 随机字符串
private String sign; // 签名
private String result_code; // 业务结果
private String err_code; // 错误代码
private String err_code_des; // 错误代码描述
private String openid; // 用户标识
private String is_subscribe; // 是否关注公众号
private String trade_type; // 交易类型
private String bank_type; // 付款银行
private String total_fee; // 总金额
private String fee_type; // 货币种类
private String cash_fee; // 现金支付金额
private String cash_fee_type; // 现金支付货币类型
private String coupon_fee; // 代金券或立减优惠金额
private String coupon_count; // 代金券或立减优惠使用数量
private String transaction_id; // 微信支付订单号
private String out_trade_no; // 单个代金券或立减优惠支付金额
private String attach; // 商家数据包
private String time_end; // 支付完成时间
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getBank_type() {
return bank_type;
}
public void setBank_type(String bank_type) {
this.bank_type = bank_type;
}
public String getCash_fee() {
return cash_fee;
}
public void setCash_fee(String cash_fee) {
this.cash_fee = cash_fee;
}
public String getCash_fee_type() {
return cash_fee_type;
}
public void setCash_fee_type(String cash_fee_type) {
this.cash_fee_type = cash_fee_type;
}
public String getCoupon_count() {
return coupon_count;
}
public void setCoupon_count(String coupon_count) {
this.coupon_count = coupon_count;
}
public String getCoupon_fee() {
return coupon_fee;
}
public void setCoupon_fee(String coupon_fee) {
this.coupon_fee = coupon_fee;
}
public String getDevice_info() {
return device_info;
}
public void setDevice_info(String device_info) {
this.device_info = device_info;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getFee_type() {
return fee_type;
}
public void setFee_type(String fee_type) {
this.fee_type = fee_type;
}
public String getIs_subscribe() {
return is_subscribe;
}
public void setIs_subscribe(String is_subscribe) {
this.is_subscribe = is_subscribe;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getNonce_str() {
return nonce_str;
}
public void setNonce_str(String nonce_str) {
this.nonce_str = nonce_str;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getTime_end() {
return time_end;
}
public void setTime_end(String time_end) {
this.time_end = time_end;
}
public String getTotal_fee() {
return total_fee;
}
public void setTotal_fee(String total_fee) {
this.total_fee = total_fee;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
}
package org.xxpay.service.channel.tencent.protocol.notify_protocol;
/**
* User: dingzhiwei
* Date: 2016/05/13
* Time: 15:20
*/
import java.io.Serializable;
/**
* 统一下单通知响应数据
*/
public class NotifyUnifiedOrderResData implements Serializable {
private static final long serialVersionUID = -2089583048909946750L;
//协议层
private String return_code; // 返回状态码
private String return_msg; // 返回信息
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
}
package org.xxpay.service.channel.tencent.protocol.order_protocol;
/**
* User: dingzhiwei
* Date: 2016/04/29
* Time: 18:06
*/
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 请求统一下单API需要提交的数据
*/
public class UnifiedOrderReqData {
private String appid = ""; // 公众号或应用ID
private String mch_id = ""; // 商户号
private String device_info = ""; // 设备号
private String nonce_str = ""; // 随机字符串
private String sign = ""; // 签名
private String body = ""; // 商品描述
private String detail = ""; // 商品详情
private String attach = ""; // 附加数据
private String out_trade_no = ""; // 商户订单号
private String fee_type = ""; // 货币类型
private String total_fee = ""; // 总金额
private String spbill_create_ip = ""; // 终端IP
private String time_start = ""; // 交易起始时间
private String time_expire = ""; // 交易结束时间
private String goods_tag = ""; // 商品标记
private String notify_url = ""; // 通知地址
private String trade_type = ""; // 交易类型
private String product_id = ""; // 商品ID
private String limit_pay = ""; // 指定支付方式
private String openid = ""; // 用户标识
/**
*
* @param deviceInfo 终端设备号(门店号或收银设备ID),注意:PC网页或公众号内支付请传"WEB"
* @param body 商品或支付单简要描述
* @param detail 商品名称明细列表
* @param attach 附加数据,在查询API和支付通知中原样返回,该字段主要用于商户携带订单的自定义数据
* @param outTradeNo 商户系统内部的订单号,32个字符内、可包含字母, 其他说明见商户订单号
* @param feeType 符合ISO 4217标准的三位字母代码,默认人民币:CNY,其他值列表详见货币类型
* @param totalFee 订单总金额,单位为分,详见支付金额
* @param spBillCreateIP APP和网页支付提交用户端ip,Native支付填调用微信支付API的机器IP
* @param timeStart 订单生成时间,格式为yyyyMMddHHmmss,如2009年12月25日9点10分10秒表示为20091225091010。其他详见时间规则
* @param timeExpire 订单失效时间,格式为yyyyMMddHHmmss,如2009年12月27日9点10分10秒表示为20091227091010。其他详见时间规则,注意:最短失效时间间隔必须大于5分钟
* @param goodsTag 商品标记,代金券或立减优惠功能的参数,说明详见代金券或立减优惠
* @param notifyUrl 接收微信支付异步通知回调地址,通知url必须为直接可访问的url,不能携带参数
* @param tradeType 取值:JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付
* @param productId trade_type=NATIVE,此参数必传。此id为二维码中包含的商品ID,商户自行定义
* @param limitPay no_credit--指定不能使用信用卡支付
* @param openId trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识。
*/
public UnifiedOrderReqData(Configure configure, String deviceInfo, String body, String detail, String attach, String outTradeNo, String feeType,
String totalFee, String spBillCreateIP, String timeStart, String timeExpire, String goodsTag,
String notifyUrl, String tradeType, String productId, String limitPay, String openId){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
//支付终端设备号,方便追溯这笔交易发生在哪台终端设备上
setDevice_info(deviceInfo);
//要支付的商品的描述信息,用户会在支付成功页面里看到这个信息
setBody(body);
setDetail(detail);
//商户系统内部的订单号,32个字符内可包含字母, 确保在商户系统唯一
setOut_trade_no(outTradeNo);
setFee_type(feeType);
//订单总金额,单位为“分”,只能整数
setTotal_fee(totalFee);
//订单生成的机器IP
setSpbill_create_ip(spBillCreateIP);
//订单生成时间, 格式为yyyyMMddHHmmss,如2009年12 月25 日9 点10 分10 秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器
setTime_start(timeStart);
//订单失效时间,格式同上
setTime_expire(timeExpire);
//商品标记,微信平台配置的商品标记,用于优惠券或者满减使用
setGoods_tag(goodsTag);
setNotify_url(notifyUrl);
setTrade_type(tradeType);
setProduct_id(productId);
setLimit_pay(limitPay);
setOpenid(openId);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//附加信息
setAttach(attach);
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getTotal_fee() {
return total_fee;
}
public void setTotal_fee(String total_fee) {
this.total_fee = total_fee;
}
public String getSpbill_create_ip() {
return spbill_create_ip;
}
public void setSpbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_ip;
}
public String getTime_start() {
return time_start;
}
public void setTime_start(String time_start) {
this.time_start = time_start;
}
public String getTime_expire() {
return time_expire;
}
public void setTime_expire(String time_expire) {
this.time_expire = time_expire;
}
public String getGoods_tag() {
return goods_tag;
}
public void setGoods_tag(String goods_tag) {
this.goods_tag = goods_tag;
}
public String getDetail() {
return detail;
}
public void setDetail(String detail) {
this.detail = detail;
}
public String getFee_type() {
return fee_type;
}
public void setFee_type(String fee_type) {
this.fee_type = fee_type;
}
public String getNotify_url() {
return notify_url;
}
public void setNotify_url(String notify_url) {
this.notify_url = notify_url;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getProduct_id() {
return product_id;
}
public void setProduct_id(String product_id) {
this.product_id = product_id;
}
public String getLimit_pay() {
return limit_pay;
}
public void setLimit_pay(String limit_pay) {
this.limit_pay = limit_pay;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.order_protocol;
/**
* User: dingzhiwei
* Date: 2016/04/29
* Time: 18:42
*/
/**
* 统一下单提交Post数据给到API之后,API会返回XML格式的数据,这个类用来装这些数据
*/
public class UnifiedOrderResData {
//协议层
private String return_code = ""; // 返回状态码
private String return_msg = ""; // 返回信息
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String appid = ""; // 应用APPID
private String mch_id = ""; // 商户号
private String device_info = ""; // 设备号
private String nonce_str = ""; // 随机字符串
private String sign = ""; // 签名
private String result_code = ""; // 业务结果
private String err_code = ""; // 错误代码
private String err_code_des = ""; // 错误代码描述
//业务返回的具体数据(以下字段在return_code 和result_code 都为SUCCESS 的时候有返回)
private String trade_type = ""; // 交易类型
private String prepay_id = ""; // 预支付交易会话标识
private String code_url = ""; // 二维码链接
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
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 String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getPrepay_id() {
return prepay_id;
}
public void setPrepay_id(String prepay_id) {
this.prepay_id = prepay_id;
}
public String getCode_url() {
return code_url;
}
public void setCode_url(String code_url) {
this.code_url = code_url;
}
}
package org.xxpay.service.channel.tencent.protocol.pay_protocol;
/**
* User: rizenguo
* Date: 2014/10/22
* Time: 21:29
*/
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import org.xxpay.common.constant.PayConstant;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* 请求被扫支付API需要提交的数据
*/
public class ScanPayReqData {
//每个字段具体的意思请查看API文档
private String appid = "";
private String mch_id = "";
private String device_info = "";
private String nonce_str = "";
private String sign = "";
private String body = "";
private String attach = "";
private String out_trade_no = "";
private int total_fee = 0;
private String spbill_create_ip = "";
private String time_start = "";
private String time_expire = "";
private String goods_tag = "";
private String auth_code = "";
/**
* @param authCode 这个是扫码终端设备从用户手机上扫取到的支付授权号,这个号是跟用户用来支付的银行卡绑定的,有效期是1分钟
* @param body 要支付的商品的描述信息,用户会在支付成功页面里看到这个信息
* @param attach 支付订单里面可以填的附加数据,API会将提交的这个附加数据原样返回
* @param outTradeNo 商户系统内部的订单号,32个字符内可包含字母, 确保在商户系统唯一
* @param totalFee 订单总金额,单位为“分”,只能整数
* @param deviceInfo 商户自己定义的扫码支付终端设备号,方便追溯这笔交易发生在哪台终端设备上
* @param spBillCreateIP 订单生成的机器IP
* @param timeStart 订单生成时间, 格式为yyyyMMddHHmmss,如2009年12 月25 日9 点10 分10 秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器
* @param timeExpire 订单失效时间,格式同上
* @param goodsTag 商品标记,微信平台配置的商品标记,用于优惠券或者满减使用
*/
public ScanPayReqData(Configure configure, String authCode,String body,String attach,String outTradeNo,int totalFee,String deviceInfo,String spBillCreateIP,String timeStart,String timeExpire,String goodsTag){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
//这个是扫码终端设备从用户手机上扫取到的支付授权号,这个号是跟用户用来支付的银行卡绑定的,有效期是1分钟
//调试的时候可以在微信上打开“钱包”里面的“刷卡”,将扫码页面里的那一串14位的数字输入到这里来,进行提交验证
//记住out_trade_no这个订单号可以将这一笔支付进行退款
setAuth_code(authCode);
//要支付的商品的描述信息,用户会在支付成功页面里看到这个信息
setBody(body);
//支付订单里面可以填的附加数据,API会将提交的这个附加数据原样返回,有助于商户自己可以注明该笔消费的具体内容,方便后续的运营和记录
setAttach(attach);
//商户系统内部的订单号,32个字符内可包含字母, 确保在商户系统唯一
setOut_trade_no(outTradeNo);
//订单总金额,单位为“分”,只能整数
setTotal_fee(totalFee);
//商户自己定义的扫码支付终端设备号,方便追溯这笔交易发生在哪台终端设备上
setDevice_info(deviceInfo);
//订单生成的机器IP
setSpbill_create_ip(spBillCreateIP);
//订单生成时间, 格式为yyyyMMddHHmmss,如2009年12 月25 日9 点10 分10 秒表示为20091225091010。时区为GMT+8 beijing。该时间取自商户服务器
setTime_start(timeStart);
//订单失效时间,格式同上
setTime_expire(timeExpire);
//商品标记,微信平台配置的商品标记,用于优惠券或者满减使用
setGoods_tag(goodsTag);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 String getBody() {
return body;
}
public void setBody(String body) {
this.body = body;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public int getTotal_fee() {
return total_fee;
}
public void setTotal_fee(int total_fee) {
this.total_fee = total_fee;
}
public String getSpbill_create_ip() {
return spbill_create_ip;
}
public void setSpbill_create_ip(String spbill_create_ip) {
this.spbill_create_ip = spbill_create_ip;
}
public String getTime_start() {
return time_start;
}
public void setTime_start(String time_start) {
this.time_start = time_start;
}
public String getTime_expire() {
return time_expire;
}
public void setTime_expire(String time_expire) {
this.time_expire = time_expire;
}
public String getGoods_tag() {
return goods_tag;
}
public void setGoods_tag(String goods_tag) {
this.goods_tag = goods_tag;
}
public String getAuth_code() {
return auth_code;
}
public void setAuth_code(String auth_code) {
this.auth_code = auth_code;
}
public Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.pay_protocol;
/**
* User: rizenguo
* Date: 2014/10/22
* Time: 16:42
*/
/**
* 被扫支付提交Post数据给到API之后,API会返回XML格式的数据,这个类用来装这些数据
*/
public class ScanPayResData {
//协议层
private String return_code = "";
private String return_msg = "";
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String appid = "";
private String mch_id = "";
private String nonce_str = "";
private String sign = "";
private String result_code = "";
private String err_code = "";
private String err_code_des = "";
private String device_info = "";
//业务返回的具体数据(以下字段在return_code 和result_code 都为SUCCESS 的时候有返回)
private String openid = "";
private String is_subscribe = "";
private String trade_type = "";
private String bank_type = "";
private String total_fee = "";
private String coupon_fee = "";
private String fee_type = "";
private String transaction_id = "";
private String out_trade_no = "";
private String attach = "";
private String time_end = "";
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
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 String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getIs_subscribe() {
return is_subscribe;
}
public void setIs_subscribe(String is_subscribe) {
this.is_subscribe = is_subscribe;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getBank_type() {
return bank_type;
}
public void setBank_type(String bank_type) {
this.bank_type = bank_type;
}
public String getTotal_fee() {
return total_fee;
}
public void setTotal_fee(String total_fee) {
this.total_fee = total_fee;
}
public String getCoupon_fee() {
return coupon_fee;
}
public void setCoupon_fee(String coupon_fee) {
this.coupon_fee = coupon_fee;
}
public String getFee_type() {
return fee_type;
}
public void setFee_type(String fee_type) {
this.fee_type = fee_type;
}
public String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getTime_end() {
return time_end;
}
public void setTime_end(String time_end) {
this.time_end = time_end;
}
}
package org.xxpay.service.channel.tencent.protocol.pay_query_protocol;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import org.springframework.util.StringUtils;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 13:54
*/
public class ScanPayQueryReqData {
//每个字段具体的意思请查看API文档
private String appid;
private String mch_id;
private String transaction_id;
private String out_trade_no;
private String nonce_str;
private String sign;
/**
* 请求支付查询服务
* @param transactionID 是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。建议优先使用
* @param outTradeNo 商户系统内部的订单号,transaction_id 、out_trade_no 二选一,如果同时存在优先级:transaction_id>out_trade_no
* @return API返回的XML数据
* @throws Exception
*/
public ScanPayQueryReqData(Configure configure, String transactionID, String outTradeNo){
//--------------------------------------------------------------------
//以下是测试数据,请商户按照自己的实际情况填写具体的值进去
//--------------------------------------------------------------------
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
//transaction_id是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。
if(!StringUtils.isEmpty(transactionID)) setTransaction_id(transactionID);
//商户系统自己生成的唯一的订单号
if(!StringUtils.isEmpty(outTradeNo)) setOut_trade_no(outTradeNo);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
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 Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.pay_query_protocol;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 13:54
*/
public class ScanPayQueryResData {
//协议层
private String return_code = "";
private String return_msg = "";
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String appid = "";
private String mch_id = "";
private String sub_mch_id = "";//新增
private String nonce_str = "";
private String sign = "";
private String result_code = "";
private String err_code = "";
private String err_code_des = "";
//以下字段在return_code 和result_code 都为SUCCESS 的时候有返回
private String trade_state = "";
//trade_state的几种可能取值:
// SUCCESS--支付成功
// REFUND--转入退款
// NOTPAY--未支付
// CLOSED--已关闭
// REVOKED--已撤销
// USERPAYING--用户支付中
// NOPAY--未支付(确认支付超时)
// PAYERROR--支付失败(其他原因,
// 如银行返回失败)
//以下字段在trade_state 为SUCCESS 或者REFUND 的时候有返回
private String device_info = "";
private String openid = "";
private String is_subscribe = "";
private String trade_type = "";
private String bank_type = "";
private String total_fee = "";
private String coupon_fee = "";
private String fee_type = "";
private String transaction_id = "";
private String out_trade_no = "";
private String attach = "";
private String time_end = "";
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
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 getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_mch_id;
}
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 String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getTrade_state() {
return trade_state;
}
public void setTrade_state(String trade_state) {
this.trade_state = trade_state;
}
public String getDevice_info() {
return device_info;
}
public void setDevice_info(String device_info) {
this.device_info = device_info;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getIs_subscribe() {
return is_subscribe;
}
public void setIs_subscribe(String is_subscribe) {
this.is_subscribe = is_subscribe;
}
public String getTrade_type() {
return trade_type;
}
public void setTrade_type(String trade_type) {
this.trade_type = trade_type;
}
public String getBank_type() {
return bank_type;
}
public void setBank_type(String bank_type) {
this.bank_type = bank_type;
}
public String getTotal_fee() {
return total_fee;
}
public void setTotal_fee(String total_fee) {
this.total_fee = total_fee;
}
public String getCoupon_fee() {
return coupon_fee;
}
public void setCoupon_fee(String coupon_fee) {
this.coupon_fee = coupon_fee;
}
public String getFee_type() {
return fee_type;
}
public void setFee_type(String fee_type) {
this.fee_type = fee_type;
}
public String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getAttach() {
return attach;
}
public void setAttach(String attach) {
this.attach = attach;
}
public String getTime_end() {
return time_end;
}
public void setTime_end(String time_end) {
this.time_end = time_end;
}
}
package org.xxpay.service.channel.tencent.protocol.redpack_protocol;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* Created by dingzhiwei on 2016/6/3.
*/
public class QueryRedpackReqData {
private String nonce_str = ""; // 随机字符串
private String sign = ""; // 签名
private String mch_billno = ""; // 商户订单号,商户订单号(每个订单号必须唯一)组成:mch_id+yyyymmdd+10位一天内不能重复的数字
private String mch_id = ""; // 商户号
private String appid = ""; // 公众号ID
private String bill_type = ""; // 订单类型,MCHT:通过商户订单号获取红包信息
/**
*
* @param mch_billno
* @param bill_type
*/
public QueryRedpackReqData(Configure configure, String mch_billno, String bill_type){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
setMch_billno(mch_billno);
setBill_type(bill_type);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
public String getAppid() {
return appid;
}
public void setAppid(String appid) {
this.appid = appid;
}
public String getBill_type() {
return bill_type;
}
public void setBill_type(String bill_type) {
this.bill_type = bill_type;
}
public String getMch_billno() {
return mch_billno;
}
public void setMch_billno(String mch_billno) {
this.mch_billno = mch_billno;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
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 Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.redpack_protocol;
/**
* Created by dingzhiwei on 16/6/3.
*/
public class QueryRedpackResData {
//协议层
private String return_code = ""; // 返回状态码
private String return_msg = ""; // 返回信息
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String sign = ""; // 签名
private String result_code = ""; // 业务结果
private String err_code = ""; // 错误代码
private String err_code_des = ""; // 错误代码描述
//业务返回的具体数据(以下字段在return_code 和result_code 都为SUCCESS 的时候有返回)
private String mch_billno = ""; // 商户订单号
private String mch_id = ""; // 商户号
private String detail_id = ""; // 红包单号
private String status = ""; // 状态,SENDING:发放中 SENT:已发放待领取 FAILED:发放失败 RECEIVED:已领取 REFUND:已退款
private String send_type = ""; // 发放类型,API:通过API接口发放 UPLOAD:通过上传文件方式发放 ACTIVITY:通过活动方式发放
private String hb_type = ""; // 红包类型,GROUP:裂变红包 NORMAL:普通红包
private String total_num = ""; // 红包个数
private String total_amount = ""; // 红包总金额(单位分)
private String reason = ""; // 发送失败原因
private String send_time = ""; // 红包发送时间
private String refund_time = ""; // 红包退款时间
private String refund_amount = ""; // 红包退款金额
private String wishing = ""; // 祝福语
private String remark = ""; // 活动描述
private String act_name = ""; // 活动名称
private String hblist = ""; // 裂变红包领取列表
private String openid = ""; // 领取红包的Openid
private String amount = ""; // 公众号appid
private String rcv_time = ""; // 领取红包的时间
public String getAct_name() {
return act_name;
}
public void setAct_name(String act_name) {
this.act_name = act_name;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
public String getDetail_id() {
return detail_id;
}
public void setDetail_id(String detail_id) {
this.detail_id = detail_id;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getHb_type() {
return hb_type;
}
public void setHb_type(String hb_type) {
this.hb_type = hb_type;
}
public String getHblist() {
return hblist;
}
public void setHblist(String hblist) {
this.hblist = hblist;
}
public String getMch_billno() {
return mch_billno;
}
public void setMch_billno(String mch_billno) {
this.mch_billno = mch_billno;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getOpenid() {
return openid;
}
public void setOpenid(String openid) {
this.openid = openid;
}
public String getRcv_time() {
return rcv_time;
}
public void setRcv_time(String rcv_time) {
this.rcv_time = rcv_time;
}
public String getReason() {
return reason;
}
public void setReason(String reason) {
this.reason = reason;
}
public String getRefund_amount() {
return refund_amount;
}
public void setRefund_amount(String refund_amount) {
this.refund_amount = refund_amount;
}
public String getRefund_time() {
return refund_time;
}
public void setRefund_time(String refund_time) {
this.refund_time = refund_time;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getSend_time() {
return send_time;
}
public void setSend_time(String send_time) {
this.send_time = send_time;
}
public String getSend_type() {
return send_type;
}
public void setSend_type(String send_type) {
this.send_type = send_type;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getTotal_num() {
return total_num;
}
public void setTotal_num(String total_num) {
this.total_num = total_num;
}
public String getWishing() {
return wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
@Override
public String toString() {
return "QueryRedpackResData{" +
"act_name='" + act_name + '\'' +
", return_code='" + return_code + '\'' +
", return_msg='" + return_msg + '\'' +
", sign='" + sign + '\'' +
", result_code='" + result_code + '\'' +
", err_code='" + err_code + '\'' +
", err_code_des='" + err_code_des + '\'' +
", mch_billno='" + mch_billno + '\'' +
", mch_id='" + mch_id + '\'' +
", detail_id='" + detail_id + '\'' +
", status='" + status + '\'' +
", send_type='" + send_type + '\'' +
", hb_type='" + hb_type + '\'' +
", total_num='" + total_num + '\'' +
", total_amount='" + total_amount + '\'' +
", reason='" + reason + '\'' +
", send_time='" + send_time + '\'' +
", refund_time='" + refund_time + '\'' +
", refund_amount='" + refund_amount + '\'' +
", wishing='" + wishing + '\'' +
", remark='" + remark + '\'' +
", hblist='" + hblist + '\'' +
", openid='" + openid + '\'' +
", amount='" + amount + '\'' +
", rcv_time='" + rcv_time + '\'' +
'}';
}
}
package org.xxpay.service.channel.tencent.protocol.redpack_protocol;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* Created by dingzhiwei on 2016/6/3.
*/
public class SendRedpackReqData {
private String nonce_str = ""; // 随机字符串
private String sign = ""; // 签名
private String mch_billno = ""; // 商户订单号,商户订单号(每个订单号必须唯一)组成:mch_id+yyyymmdd+10位一天内不能重复的数字
private String mch_id = ""; // 商户号
private String wxappid = ""; // 公众号ID
private String send_name = ""; // 商户名称,红包发送者名称
private String re_openid = ""; // 接受红包的用户
private String total_amount = ""; // 付款金额
private String total_num = ""; // 红包发放总人数
private String wishing = ""; // 红包祝福语
private String client_ip = ""; // 调用接口的机器Ip地址
private String act_name = ""; // 活动名称
private String remark = ""; // 备注
/**
*
* @param mch_billno
* @param send_name
* @param re_openid
* @param total_amount
* @param total_num
* @param wishing
* @param act_name
* @param remark
*/
public SendRedpackReqData(Configure configure, String mch_billno, String send_name, String re_openid,
String total_amount, String total_num, String wishing, String act_name, String remark){
//微信分配的公众号ID(开通公众号之后可以获取到)
setWxappid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
setMch_billno(mch_billno);
setSend_name(send_name);
setRe_openid(re_openid);
setTotal_amount(total_amount);
setTotal_num(total_num);
setWishing(wishing);
setClient_ip(configure.getIp());
setAct_name(act_name);
setRemark(remark);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 String getMch_billno() {
return mch_billno;
}
public void setMch_billno(String mch_billno) {
this.mch_billno = mch_billno;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getWxappid() {
return wxappid;
}
public void setWxappid(String wxappid) {
this.wxappid = wxappid;
}
public String getSend_name() {
return send_name;
}
public void setSend_name(String send_name) {
this.send_name = send_name;
}
public String getRe_openid() {
return re_openid;
}
public void setRe_openid(String re_openid) {
this.re_openid = re_openid;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getTotal_num() {
return total_num;
}
public void setTotal_num(String total_num) {
this.total_num = total_num;
}
public String getWishing() {
return wishing;
}
public void setWishing(String wishing) {
this.wishing = wishing;
}
public String getClient_ip() {
return client_ip;
}
public void setClient_ip(String client_ip) {
this.client_ip = client_ip;
}
public String getAct_name() {
return act_name;
}
public void setAct_name(String act_name) {
this.act_name = act_name;
}
public String getRemark() {
return remark;
}
public void setRemark(String remark) {
this.remark = remark;
}
public Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.redpack_protocol;
/**
* Created by dingzhiwei on 16/6/3.
*/
public class SendRedpackResData {
//协议层
private String return_code = ""; // 返回状态码
private String return_msg = ""; // 返回信息
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String sign = ""; // 签名
private String result_code = ""; // 业务结果
private String err_code = ""; // 错误代码
private String err_code_des = ""; // 错误代码描述
//业务返回的具体数据(以下字段在return_code 和result_code 都为SUCCESS 的时候有返回)
private String mch_billno = ""; // 商户订单号
private String mch_id = ""; // 商户号
private String wxappid = ""; // 公众号appid
private String re_openid = ""; // 用户openId
private String total_amount = ""; // 付款金额
private String send_time = ""; // 红包发放成功时间
private String send_listid = ""; // 微信单号
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getMch_billno() {
return mch_billno;
}
public void setMch_billno(String mch_billno) {
this.mch_billno = mch_billno;
}
public String getMch_id() {
return mch_id;
}
public void setMch_id(String mch_id) {
this.mch_id = mch_id;
}
public String getRe_openid() {
return re_openid;
}
public void setRe_openid(String re_openid) {
this.re_openid = re_openid;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getSend_listid() {
return send_listid;
}
public void setSend_listid(String send_listid) {
this.send_listid = send_listid;
}
public String getSend_time() {
return send_time;
}
public void setSend_time(String send_time) {
this.send_time = send_time;
}
public String getSign() {
return sign;
}
public void setSign(String sign) {
this.sign = sign;
}
public String getTotal_amount() {
return total_amount;
}
public void setTotal_amount(String total_amount) {
this.total_amount = total_amount;
}
public String getWxappid() {
return wxappid;
}
public void setWxappid(String wxappid) {
this.wxappid = wxappid;
}
}
package org.xxpay.service.channel.tencent.protocol.refund_protocol;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import org.xxpay.common.constant.PayConstant;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 16:12
*/
public class RefundReqData {
//每个字段具体的意思请查看API文档
private String appid = "";
private String mch_id = "";
private String device_info = "";
private String nonce_str = "";
private String sign = "";
private String transaction_id = "";
private String out_trade_no = "";
private String out_refund_no = "";
private int total_fee = 0;
private int refund_fee = 0;
private String refund_fee_type = "CNY";
private String op_user_id = "";
/**
* 请求退款服务
* @param transactionID 是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。建议优先使用
* @param outTradeNo 商户系统内部的订单号,transaction_id 、out_trade_no 二选一,如果同时存在优先级:transaction_id>out_trade_no
* @param deviceInfo 微信支付分配的终端设备号,与下单一致
* @param outRefundNo 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
* @param totalFee 订单总金额,单位为分
* @param refundFee 退款总金额,单位为分,可以做部分退款
* @param opUserID 操作员帐号, 默认为商户号
* @param refundFeeType 货币类型,符合ISO 4217标准的三位字母代码,默认为CNY(人民币)
*/
public RefundReqData(Configure configure, String transactionID,String outTradeNo,String deviceInfo,String outRefundNo,int totalFee,int refundFee,String opUserID,String refundFeeType){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
//transaction_id是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。
setTransaction_id(transactionID);
//商户系统自己生成的唯一的订单号
setOut_trade_no(outTradeNo);
//微信支付分配的终端设备号,与下单一致
setDevice_info(deviceInfo);
setOut_refund_no(outRefundNo);
setTotal_fee(totalFee);
setRefund_fee(refundFee);
setOp_user_id(opUserID);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getOut_refund_no() {
return out_refund_no;
}
public void setOut_refund_no(String out_refund_no) {
this.out_refund_no = out_refund_no;
}
public int getTotal_fee() {
return total_fee;
}
public void setTotal_fee(int total_fee) {
this.total_fee = total_fee;
}
public int getRefund_fee() {
return refund_fee;
}
public void setRefund_fee(int refund_fee) {
this.refund_fee = refund_fee;
}
public String getOp_user_id() {
return op_user_id;
}
public void setOp_user_id(String op_user_id) {
this.op_user_id = op_user_id;
}
public String getRefund_fee_type() {
return refund_fee_type;
}
public void setRefund_fee_type(String refund_fee_type) {
this.refund_fee_type = refund_fee_type;
}
public Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.refund_protocol;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 16:12
*/
public class RefundResData {
//协议层
private String return_code = "";
private String return_msg = "";
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String appid = "";
private String mch_id = "";
private String sub_mch_id = "";
private String device_info = "";
private String nonce_str = "";
private String sign = "";
private String result_code = "";
private String err_code = "";
private String err_code_des = "";
private String transaction_id = "";
private String out_trade_no = "";
private String out_refund_no = "";
private String refund_id = "";
private String refund_fee = "";
private String coupon_refund_fee = "";
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
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 getSub_mch_id() {
return sub_mch_id;
}
public void setSub_mch_id(String sub_mch_id) {
this.sub_mch_id = sub_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 String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
public String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getOut_refund_no() {
return out_refund_no;
}
public void setOut_refund_no(String out_refund_no) {
this.out_refund_no = out_refund_no;
}
public String getRefund_id() {
return refund_id;
}
public void setRefund_id(String refund_id) {
this.refund_id = refund_id;
}
public String getRefund_fee() {
return refund_fee;
}
public void setRefund_fee(String refund_fee) {
this.refund_fee = refund_fee;
}
public String getCoupon_refund_fee() {
return coupon_refund_fee;
}
public void setCoupon_refund_fee(String coupon_refund_fee) {
this.coupon_refund_fee = coupon_refund_fee;
}
}
package org.xxpay.service.channel.tencent.protocol.refund_query_protocol;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/11/1
* Time: 14:09
* 用来存放退款订单数据
*/
public class RefundOrderData {
private String outRefundNo = "";//商户退款单号
private String refundID = "";//微信退款单号
private String refundChannel = "";//退款渠道
// IGINAL--原路退款
// BALANCE--退回到余额
private int refundFee = 0;//退款金额
private int couponRefundFee = 0;//企业红包退款金额
private String refundStatus = "";//退款状态
public String getOutRefundNo() {
return outRefundNo;
}
public void setOutRefundNo(String outRefundNo) {
this.outRefundNo = outRefundNo;
}
public String getRefundID() {
return refundID;
}
public void setRefundID(String refundID) {
this.refundID = refundID;
}
public String getRefundChannel() {
return refundChannel;
}
public void setRefundChannel(String refundChannel) {
this.refundChannel = refundChannel;
}
public int getRefundFee() {
return refundFee;
}
public void setRefundFee(int refundFee) {
this.refundFee = refundFee;
}
public int getCouponRefundFee() {
return couponRefundFee;
}
public void setCouponRefundFee(int couponRefundFee) {
this.couponRefundFee = couponRefundFee;
}
public String getRefundStatus() {
return refundStatus;
}
public void setRefundStatus(String refundStatus) {
this.refundStatus = refundStatus;
}
public String toMap(){
Map<String,Object> map = new LinkedHashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
StringBuilder s=new StringBuilder("{");
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
if(s.length()>0){
s.append(" ");
}
s.append(field.getName());
s.append("=");
s.append(obj.toString());
// map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
s.append("}");
return s.toString();
}
}
package org.xxpay.service.channel.tencent.protocol.refund_query_protocol;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.common.RandomStringGenerator;
import org.xxpay.service.channel.tencent.common.Signature;
import org.xxpay.common.constant.PayConstant;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 16:35
*/
public class RefundQueryReqData {
//每个字段具体的意思请查看API文档
private String appid = "";
private String mch_id = "";
private String device_info = "";
private String nonce_str = "";
private String sign = "";
private String transaction_id = "";
private String out_trade_no = "";
/**
* 请求退款查询服务
* @param transactionID 是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。建议优先使用
* @param outTradeNo 商户系统内部的订单号,transaction_id 、out_trade_no 二选一,如果同时存在优先级:transaction_id>out_trade_no
* @param deviceInfo 微信支付分配的终端设备号,与下单一致
* @param outRefundNo 商户系统内部的退款单号,商户系统内部唯一,同一退款单号多次请求只退一笔
* @param refundID 来自退款API的成功返回,微信退款单号refund_id、out_refund_no、out_trade_no 、transaction_id 四个参数必填一个,如果同事存在优先级为:refund_id>out_refund_no>transaction_id>out_trade_no
*/
public RefundQueryReqData(Configure configure, String transactionID,String outTradeNo,String deviceInfo,String outRefundNo,String refundID){
//微信分配的公众号ID(开通公众号之后可以获取到)
setAppid(configure.getAppID());
//微信支付分配的商户号ID(开通公众号的微信支付功能之后可以获取到)
setMch_id(configure.getMchID());
//transaction_id是微信系统为每一笔支付交易分配的订单号,通过这个订单号可以标识这笔交易,它由支付订单API支付成功时返回的数据里面获取到。
setTransaction_id(transactionID);
//商户系统自己生成的唯一的订单号
setOut_trade_no(outTradeNo);
//微信支付分配的终端设备号,与下单一致
setDevice_info(deviceInfo);
setOut_refund_no(outRefundNo);
//商户系统自己管理的退款号,商户自身必须保证这个号在系统内唯一
setRefund_id(refundID);
//随机字符串,不长于32 位
setNonce_str(RandomStringGenerator.getRandomStringByLength(32));
//根据API给的签名规则进行签名
String sign = Signature.getSign(toMap(), configure.getKey());
setSign(sign);//把签名数据设置到Sign这个属性中
}
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 String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public String getOut_refund_no() {
return out_refund_no;
}
public void setOut_refund_no(String out_refund_no) {
this.out_refund_no = out_refund_no;
}
public String getRefund_id() {
return refund_id;
}
public void setRefund_id(String refund_id) {
this.refund_id = refund_id;
}
private String out_refund_no;
private String refund_id;
public Map<String,Object> toMap(){
Map<String,Object> map = new HashMap<String, Object>();
Field[] fields = this.getClass().getDeclaredFields();
for (Field field : fields) {
Object obj;
try {
obj = field.get(this);
if(obj!=null){
map.put(field.getName(), obj);
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
return map;
}
}
package org.xxpay.service.channel.tencent.protocol.refund_query_protocol;
/**
* User: rizenguo
* Date: 2014/10/25
* Time: 16:36
*/
public class RefundQueryResData {
//协议层
private String return_code = "";
private String return_msg = "";
//协议返回的具体数据(以下字段在return_code 为SUCCESS 的时候有返回)
private String result_code = "";
private String err_code = "";
private String err_code_des = "";
private String appid = "";
private String mch_id = "";
private String nonce_str = "";
private String sign = "";
private String device_info = "";
private String transaction_id = "";
private String out_trade_no = "";
private int refund_count = 0;
//TODO 这里要用对象来装,因为有可能出现多个数据
private String out_refund_no = "";
private String refund_id = "";
private String refund_channel = "";
private String refund_fee = "";
private String coupon_refund_fee = "";
private String refund_status = "";
public String getReturn_code() {
return return_code;
}
public void setReturn_code(String return_code) {
this.return_code = return_code;
}
public String getReturn_msg() {
return return_msg;
}
public void setReturn_msg(String return_msg) {
this.return_msg = return_msg;
}
public String getResult_code() {
return result_code;
}
public void setResult_code(String result_code) {
this.result_code = result_code;
}
public String getErr_code() {
return err_code;
}
public void setErr_code(String err_code) {
this.err_code = err_code;
}
public String getErr_code_des() {
return err_code_des;
}
public void setErr_code_des(String err_code_des) {
this.err_code_des = err_code_des;
}
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 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 String getDevice_info() {
return device_info;
}
public void setDevice_info(String device_info) {
this.device_info = device_info;
}
public String getTransaction_id() {
return transaction_id;
}
public void setTransaction_id(String transaction_id) {
this.transaction_id = transaction_id;
}
public String getOut_trade_no() {
return out_trade_no;
}
public void setOut_trade_no(String out_trade_no) {
this.out_trade_no = out_trade_no;
}
public int getRefund_count() {
return refund_count;
}
public void setRefund_count(int refund_count) {
this.refund_count = refund_count;
}
public String getOut_refund_no() {
return out_refund_no;
}
public void setOut_refund_no(String out_refund_no) {
this.out_refund_no = out_refund_no;
}
public String getRefund_id() {
return refund_id;
}
public void setRefund_id(String refund_id) {
this.refund_id = refund_id;
}
public String getRefund_channel() {
return refund_channel;
}
public void setRefund_channel(String refund_channel) {
this.refund_channel = refund_channel;
}
public String getRefund_fee() {
return refund_fee;
}
public void setRefund_fee(String refund_fee) {
this.refund_fee = refund_fee;
}
public String getCoupon_refund_fee() {
return coupon_refund_fee;
}
public void setCoupon_refund_fee(String coupon_refund_fee) {
this.coupon_refund_fee = coupon_refund_fee;
}
public String getRefund_status() {
return refund_status;
}
public void setRefund_status(String refund_status) {
this.refund_status = refund_status;
}
}
package org.xxpay.service.channel.tencent.service;
import org.xxpay.service.channel.tencent.common.Configure;
import org.xxpay.service.channel.tencent.protocol.downloadbill_protocol.DownloadBillReqData;
/**
* User: rizenguo
* Date: 2014/10/29
* Time: 16:04
*/
public class DownloadBillService extends BaseService {
public DownloadBillService() throws IllegalAccessException, InstantiationException, ClassNotFoundException {
super(Configure.DOWNLOAD_BILL_API);
}
//ALL,返回当日所有订单信息,默认值
public static final String BILL_TYPE_ALL = "ALL";
//SUCCESS,返回当日成功支付的订单
public static final String BILL_TYPE_SUCCESS = "SUCCESS";
//REFUND,返回当日退款订单
public static final String BILL_TYPE_REFUND = "REFUND";
//REVOKED,已撤销的订单
public static final String BILL_TYPE_REVOKE = "REVOKE";
/**
* 请求对账单下载服务
* @param downloadBillReqData 这个数据对象里面包含了API要求提交的各种数据字段
* @return API返回的XML数据
* @throws Exception
*/
public String request(DownloadBillReqData downloadBillReqData) throws Exception {
//--------------------------------------------------------------------
//发送HTTPS的Post请求到API地址
//--------------------------------------------------------------------
String responseString = sendPost(downloadBillReqData);
return responseString;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册