View Javadoc
1   package com.foxinmy.weixin4j.api;
2   
3   import java.math.BigDecimal;
4   import java.util.ArrayList;
5   import java.util.Date;
6   import java.util.List;
7   import java.util.Map;
8   import java.util.concurrent.Callable;
9   import java.util.concurrent.CompletionService;
10  import java.util.concurrent.ExecutorCompletionService;
11  import java.util.concurrent.ExecutorService;
12  import java.util.concurrent.Executors;
13  import java.util.concurrent.Future;
14  
15  import com.alibaba.fastjson.JSON;
16  import com.alibaba.fastjson.JSONObject;
17  import com.alibaba.fastjson.TypeReference;
18  import com.foxinmy.weixin4j.exception.WeixinException;
19  import com.foxinmy.weixin4j.http.weixin.WeixinResponse;
20  import com.foxinmy.weixin4j.model.WeixinPayAccount;
21  import com.foxinmy.weixin4j.model.paging.Pageable;
22  import com.foxinmy.weixin4j.payment.mch.CorpPayment;
23  import com.foxinmy.weixin4j.payment.mch.CorpPaymentRecord;
24  import com.foxinmy.weixin4j.payment.mch.CorpPaymentResult;
25  import com.foxinmy.weixin4j.payment.mch.Redpacket;
26  import com.foxinmy.weixin4j.payment.mch.RedpacketRecord;
27  import com.foxinmy.weixin4j.payment.mch.RedpacketSendResult;
28  import com.foxinmy.weixin4j.payment.mch.SettlementRecord;
29  import com.foxinmy.weixin4j.type.CurrencyType;
30  import com.foxinmy.weixin4j.util.DateUtil;
31  import com.foxinmy.weixin4j.util.RandomUtil;
32  import com.foxinmy.weixin4j.util.StringUtil;
33  import com.foxinmy.weixin4j.xml.XmlStream;
34  
35  /**
36   * 现金API
37   *
38   * @className CashApi
39   * @author jinyu(foxinmy@gmail.com)
40   * @date 2015年3月28日
41   * @since JDK 1.6
42   * @see <a href=
43   *      "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_1">
44   *      现金红包</a>
45   * @see <a href=
46   *      "https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1">
47   *      企业付款</a>
48   * @deprecated 商户平台API迁移到子模块weixin4j-pay
49   */
50  @Deprecated
51  public class CashApi extends MchApi {
52  
53  	public CashApi(WeixinPayAccount weixinAccount) {
54  		super(weixinAccount);
55  	}
56  
57  	/**
58  	 * 发放红包 企业向微信用户个人发现金红包
59  	 *
60  	 * @param redpacket
61  	 *            红包信息
62  	 * @return 发放结果
63  	 * @see com.foxinmy.weixin4j.payment.mch.Redpacket
64  	 * @see com.foxinmy.weixin4j.payment.mch.RedpacketSendResult
65  	 * @see <a href=
66  	 *      "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5">
67  	 *      发放现金红包接口</a>
68  	 * @see <a href=
69  	 *      "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=16_5">
70  	 *      发放裂变红包接口</a>
71  	 * @throws WeixinException
72  	 */
73  	public RedpacketSendResult sendRedpack(Redpacket redpacket)
74  			throws WeixinException {
75  		String appId = redpacket.getAppId();
76  		super.declareMerchant(redpacket);
77  		final JSONObject obj = (JSONObject) JSON.toJSON(redpacket);
78  		if (StringUtil.isNotBlank(appId)) {
79  			obj.put("appid", appId);
80  		}
81  		obj.put("wxappid", obj.remove("appid"));
82  		final String redpack_uri = redpacket.getTotalNum() > 1 ? getRequestUri("groupredpack_send_uri")
83  				: getRequestUri("redpack_send_uri");
84  		obj.put("sign", weixinSignature.sign(obj));
85  		String param = XmlStream.map2xml(obj);
86  		WeixinResponse response = getWeixinSSLExecutor().post(redpack_uri,
87  				param);
88  		String text = response.getAsString()
89  				.replaceFirst("<wxappid>", "<appid>")
90  				.replaceFirst("</wxappid>", "</appid>");
91  		return XmlStream.fromXML(text, RedpacketSendResult.class);
92  	}
93  
94  	/**
95  	 * 批量发放红包 企业向微信用户个人发现金红包
96  	 *
97  	 * @param redpackets
98  	 *            多个红包信息
99  	 * @return 发放结果
100 	 * @see #sendRedpacks(Redpacket...)
101 	 * @throws WeixinException
102 	 */
103 	public List<Future<RedpacketSendResult>> sendRedpacks(
104 			Redpacket... redpackets) {
105 		ExecutorService sendExecutor = Executors.newFixedThreadPool(Math.max(1,
106 				redpackets.length / 10)); // 十分之一?
107 		CompletionService<RedpacketSendResult> completion = new ExecutorCompletionService<RedpacketSendResult>(
108 				sendExecutor);
109 		List<Future<RedpacketSendResult>> callSendList = new ArrayList<Future<RedpacketSendResult>>(
110 				redpackets.length);
111 		for (final Redpacket redpacket : redpackets) {
112 			Future<RedpacketSendResult> futureSend = completion
113 					.submit(new Callable<RedpacketSendResult>() {
114 						@Override
115 						public RedpacketSendResult call() throws Exception {
116 							return sendRedpack(redpacket);
117 						}
118 					});
119 			callSendList.add(futureSend);
120 		}
121 		// 关闭启动线程,不再接受新的任务
122 		sendExecutor.shutdown();
123 		return callSendList;
124 	}
125 
126 	/**
127 	 * 查询红包记录
128 	 *
129 	 * @param outTradeNo
130 	 *            商户发放红包的商户订单号
131 	 * @return 红包记录
132 	 * @see com.foxinmy.weixin4j.payment.mch.RedpacketRecord
133 	 * @see <a href=
134 	 *      "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_7&index=6">
135 	 *      查询现金红包接口</a>
136 	 * @see <a href=
137 	 *      "https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=16_6">
138 	 *      查询裂变红包接口</a>
139 	 * @throws WeixinException
140 	 */
141 	public RedpacketRecord queryRedpack(String outTradeNo)
142 			throws WeixinException {
143 		Map<String, String> para = createBaseRequestMap(null);
144 		para.put("bill_type", "MCHT");
145 		para.put("mch_billno", outTradeNo);
146 		para.put("sign", weixinSignature.sign(para));
147 		String param = XmlStream.map2xml(para);
148 		WeixinResponse response = getWeixinSSLExecutor().post(
149 				getRequestUri("redpack_query_uri"), param);
150 		return response.getAsObject(new TypeReference<RedpacketRecord>() {
151 		});
152 	}
153 
154 	/**
155 	 * 企业付款为企业提供付款至用户零钱的能力
156 	 *
157 	 * @param payment 付款信息
158 	 * @return 付款结果
159 	 * @see com.foxinmy.weixin4j.payment.mch.CorpPayment
160 	 * @see com.foxinmy.weixin4j.payment.mch.CorpPaymentResult
161 	 * @see <a href="https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2">企业付款</a>
162 	 * @see <a href="https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_1">场景介绍(使用条件、付款资金、付款规则等)</a>
163 	 * @throws WeixinException
164 	 */
165 	public CorpPaymentResult sendCorpPayment(CorpPayment payment)
166 			throws WeixinException {
167 		super.declareMerchant(payment);
168 		JSONObject obj = (JSONObject) JSON.toJSON(payment);
169 		obj.put("mchid", obj.remove("mch_id"));
170 		obj.put("mch_appid", obj.remove("appid"));
171 		obj.put("sign", weixinSignature.sign(obj));
172 		String param = XmlStream.map2xml(obj);
173 		WeixinResponse response = getWeixinSSLExecutor().post(
174 				getRequestUri("corppayment_send_uri"), param);
175 		String text = response.getAsString()
176 				.replaceFirst("<mch_appid>", "<appid>")
177 				.replaceFirst("</mch_appid>", "</appid>")
178 				.replaceFirst("<mchid>", "<mch_id>")
179 				.replaceFirst("</mchid>", "</mch_id>");
180 		return XmlStream.fromXML(text, CorpPaymentResult.class);
181 	}
182 
183 	/**
184 	 * 企业付款查询 用于商户的企业付款操作进行结果查询,返回付款操作详细结果
185 	 *
186 	 * @param outTradeNo
187 	 *            商户调用企业付款API时使用的商户订单号
188 	 * @return 付款记录
189 	 * @see com.foxinmy.weixin4j.payment.mch.CorpPaymentRecord
190 	 * @see <a href=
191 	 *      "https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3">
192 	 *      企业付款查询接口</a>
193 	 * @throws WeixinException
194 	 */
195 	public CorpPaymentRecord queryCorpPayment(String outTradeNo)
196 			throws WeixinException {
197 		JSONObject obj = new JSONObject();
198 		obj.put("nonce_str", RandomUtil.generateString(16));
199 		obj.put("mch_id", weixinAccount.getMchId());
200 		obj.put("appid", weixinAccount.getId());
201 		obj.put("partner_trade_no", outTradeNo);
202 		obj.put("sign", weixinSignature.sign(obj));
203 		String param = XmlStream.map2xml(obj);
204 		WeixinResponse response = getWeixinSSLExecutor().post(
205 				getRequestUri("corppayment_query_uri"), param);
206 		return response.getAsObject(new TypeReference<CorpPaymentRecord>() {
207 		});
208 	}
209 
210 	/**
211 	 * 查询结算资金
212 	 *
213 	 * @param status
214 	 *            是否结算
215 	 * @param pageable
216 	 *            分页数据
217 	 * @param start
218 	 *            开始日期 查询未结算记录时,该字段可不传
219 	 * @param end
220 	 *            结束日期 查询未结算记录时,该字段可不传
221 	 * @return 结算金额记录
222 	 * @throws WeixinException
223 	 * @see com.foxinmy.weixin4j.payment.mch.SettlementRecord
224 	 * @see <a href=
225 	 *      "https://pay.weixin.qq.com/wiki/doc/api/external/micropay.php?chapter=9_14&index=7">
226 	 *      查询结算资金接口</a>
227 	 */
228 	public SettlementRecord querySettlement(boolean status, Pageable pageable,
229 			Date start, Date end) throws WeixinException {
230 		JSONObject obj = new JSONObject();
231 		obj.put("nonce_str", RandomUtil.generateString(16));
232 		obj.put("mch_id", weixinAccount.getMchId());
233 		obj.put("appid", weixinAccount.getId());
234 		obj.put("usetag", status ? 1 : 2);
235 		obj.put("offset", pageable.getOffset());
236 		obj.put("limit", pageable.getPageSize());
237 		if (start != null) {
238 			obj.put("date_start", DateUtil.fortmat2yyyyMMdd(start));
239 		}
240 		if (end != null) {
241 			obj.put("date_end", DateUtil.fortmat2yyyyMMdd(end));
242 		}
243 		obj.put("sign", weixinSignature.sign(obj));
244 		String param = XmlStream.map2xml(obj);
245 		WeixinResponse response = weixinExecutor.post(
246 				getRequestUri("settlement_query_uri"), param);
247 		return response.getAsObject(new TypeReference<SettlementRecord>() {
248 		});
249 	}
250 
251 	/**
252 	 * 查询汇率
253 	 *
254 	 * @param currencyType
255 	 *            外币币种
256 	 * @param date
257 	 *            日期 不填则默认当天
258 	 * @return 汇率 例如美元兑换人民币的比例为6.5
259 	 * @throws WeixinException
260 	 * @see <a href=
261 	 *      "https://pay.weixin.qq.com/wiki/doc/api/external/micropay.php?chapter=9_15&index=8">
262 	 *      查询汇率接口</a>
263 	 */
264 	public double queryExchageRate(CurrencyType currencyType, Date date)
265 			throws WeixinException {
266 		if (date == null) {
267 			date = new Date();
268 		}
269 		JSONObject obj = new JSONObject();
270 		obj.put("mch_id", weixinAccount.getMchId());
271 		obj.put("appid", weixinAccount.getId());
272 		obj.put("sub_mch_id", weixinAccount.getSubMchId());
273 		obj.put("fee_type", currencyType.name());
274 		obj.put("date", DateUtil.fortmat2yyyyMMdd(date));
275 		obj.put("sign", weixinSignature.sign(obj));
276 		String param = XmlStream.map2xml(obj);
277 		WeixinResponse response = weixinExecutor.post(
278 				getRequestUri("exchagerate_query_uri"), param);
279 		BigDecimal rate = new BigDecimal(XmlStream.xml2map(
280 				response.getAsString()).get("rate"));
281 		return rate.divide(new BigDecimal(100000000d)).doubleValue();
282 	}
283 }