Skip to content

Commit 175fa42

Browse files
committed
微信V3支付与微信V3合单支付案例实现
1 parent 6885cac commit 175fa42

8 files changed

Lines changed: 368 additions & 93 deletions

File tree

Lines changed: 307 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,307 @@
1+
2+
package com.egzosn.pay.demo.controller;
3+
4+
5+
import java.io.ByteArrayOutputStream;
6+
import java.io.IOException;
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Map;
10+
11+
import javax.annotation.PostConstruct;
12+
import javax.imageio.ImageIO;
13+
import javax.servlet.http.HttpServletRequest;
14+
15+
import org.springframework.web.bind.annotation.RequestMapping;
16+
import org.springframework.web.bind.annotation.RestController;
17+
18+
import com.egzosn.pay.common.bean.CertStoreType;
19+
import com.egzosn.pay.common.bean.RefundOrder;
20+
import com.egzosn.pay.demo.request.QueryOrder;
21+
import com.egzosn.pay.demo.service.handler.WxV3CombinePayMessageHandler;
22+
import com.egzosn.pay.web.support.HttpRequestNoticeParams;
23+
import com.egzosn.pay.wx.v3.api.WxCombinePayService;
24+
import com.egzosn.pay.wx.v3.api.WxPayConfigStorage;
25+
import com.egzosn.pay.wx.v3.bean.WxTransactionType;
26+
import com.egzosn.pay.wx.v3.bean.combine.CombineAmount;
27+
import com.egzosn.pay.wx.v3.bean.combine.CombineCloseOrder;
28+
import com.egzosn.pay.wx.v3.bean.combine.CombinePayOrder;
29+
import com.egzosn.pay.wx.v3.bean.combine.CombineSubOrder;
30+
import com.egzosn.pay.wx.v3.bean.order.H5Info;
31+
import com.egzosn.pay.wx.v3.bean.order.SceneInfo;
32+
import com.egzosn.pay.wx.v3.bean.order.SubOrder;
33+
import com.egzosn.pay.wx.v3.bean.response.WxRefundResult;
34+
35+
/**
36+
* 微信V3合单发起支付入口
37+
*
38+
* @author egan
39+
* email egzosn@gmail.com
40+
* date 2016/11/18 0:25
41+
*/
42+
@RestController
43+
@RequestMapping("wxV3combine")
44+
public class WxV3CombinePayController {
45+
46+
private WxCombinePayService service = null;
47+
48+
@PostConstruct //没有证书的情况下注释掉,避免启动报错
49+
public void init() {
50+
WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
51+
wxPayConfigStorage.setAppId("wxc7b993ff15a9f27c");
52+
wxPayConfigStorage.setMchId("1602947766");
53+
//V3密钥 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
54+
wxPayConfigStorage.setV3ApiKey("9bd8f0e7af4841299d782406b7774f56");
55+
wxPayConfigStorage.setNotifyUrl("http://sailinmu.iok.la/wxV3/payBack.json");
56+
wxPayConfigStorage.setReturnUrl("http://sailinmu.iok.la/wxV3/payBack.json");
57+
wxPayConfigStorage.setInputCharset("utf-8");
58+
//使用证书时设置为true
59+
wxPayConfigStorage.setCertSign(true);
60+
//商户API证书 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml
61+
wxPayConfigStorage.setApiClientKeyP12("E:\\Documents\\gitee\\支付\\yifenli_mall.p12");
62+
wxPayConfigStorage.setCertStoreType(CertStoreType.PATH);
63+
service = new WxCombinePayService(wxPayConfigStorage);
64+
//设置回调消息处理
65+
//TODO {@link com.egzosn.pay.demo.controller.WxPayController#payBack}
66+
service.setPayMessageHandler(new WxV3CombinePayMessageHandler());
67+
}
68+
69+
70+
/**
71+
* 跳到支付页面
72+
* 针对实时支付
73+
*
74+
* @return 跳到支付页面
75+
*/
76+
@RequestMapping(value = "toPay.html", produces = "text/html;charset=UTF-8")
77+
public String toPay() {
78+
CombinePayOrder order = new CombinePayOrder();
79+
SceneInfo sceneInfo = new SceneInfo();
80+
sceneInfo.setPayerClientIp("用户终端IP ");
81+
sceneInfo.setDeviceId("终端设备号(门店号或收银设备ID) 。为了方便问题定位,H5支付场景下,该字段必填");
82+
sceneInfo.setH5Info(new H5Info("场景类型,枚举值:\n" +
83+
"iOS:IOS移动应用;\n" +
84+
"Android:安卓移动应用;\n" +
85+
"Wap:WAP网站应用;"));
86+
order.setSceneInfo(sceneInfo);
87+
order.setCombineOutTradeNo("合单商户订单号");
88+
//子单信息,最多50单.
89+
List<SubOrder> subOrders = new ArrayList<>();
90+
SubOrder subOrder = new SubOrder();
91+
subOrder.setMchid("子单商户号");
92+
subOrder.setAttach("附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。 ");
93+
//"子单金额,单位为分。 "
94+
subOrder.setAmount(new CombineAmount(121));
95+
subOrder.setOutTradeNo("子单商户订单号 ");
96+
subOrder.setDescription("商品描述");
97+
subOrder.setSubMchid("二级商户商户号,由微信支付生成并下发。服务商子商户的商户号,被合单方。直连商户不用传二级商户号。 ");
98+
subOrders.add(subOrder);
99+
order.setSubOrders(subOrders);
100+
order.setTransactionType(WxTransactionType.COMBINE_H5);
101+
return service.toPay(order);
102+
}
103+
104+
/**
105+
* 公众号支付,小程序
106+
*
107+
* @return 返回jsapi所需参数
108+
*/
109+
@RequestMapping(value = "jsapi")
110+
public Map jsapi() {
111+
112+
CombinePayOrder order = new CombinePayOrder();
113+
order.setTransactionType(WxTransactionType.COMBINE_JSAPI);
114+
order.setCombineOutTradeNo("合单商户订单号");
115+
order.setOpenid("使用合单appid获取的对应用户openid。是用户在商户appid下的唯一标识。 ");
116+
//子单信息,最多50单.
117+
List<SubOrder> subOrders = new ArrayList<>();
118+
SubOrder subOrder = new SubOrder();
119+
subOrder.setMchid("子单商户号");
120+
subOrder.setAttach("附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。 ");
121+
//"子单金额,单位为分。 "
122+
subOrder.setAmount(new CombineAmount(111));
123+
subOrder.setOutTradeNo("子单商户订单号 ");
124+
subOrder.setDescription("商品描述");
125+
subOrder.setSubMchid("二级商户商户号,由微信支付生成并下发。服务商子商户的商户号,被合单方。直连商户不用传二级商户号。 ");
126+
subOrders.add(subOrder);
127+
order.setSubOrders(subOrders);
128+
Map orderInfo = service.orderInfo(order);
129+
orderInfo.put("code", 0);
130+
return orderInfo;
131+
}
132+
133+
134+
/**
135+
* 获取支付预订单信息
136+
*
137+
* @return 支付预订单信息
138+
*/
139+
@RequestMapping("app")
140+
public Map<String, Object> app() {
141+
142+
CombinePayOrder order = new CombinePayOrder();
143+
order.setTransactionType(WxTransactionType.COMBINE_APP);
144+
order.setCombineOutTradeNo("合单商户订单号");
145+
//子单信息,最多50单.
146+
List<SubOrder> subOrders = new ArrayList<>();
147+
SubOrder subOrder = new SubOrder();
148+
subOrder.setMchid("子单商户号");
149+
subOrder.setAttach("附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。 ");
150+
//"子单金额,单位为分。 "
151+
subOrder.setAmount(new CombineAmount(211));
152+
subOrder.setOutTradeNo("子单商户订单号 ");
153+
subOrder.setDescription("商品描述");
154+
subOrder.setSubMchid("二级商户商户号,由微信支付生成并下发。服务商子商户的商户号,被合单方。直连商户不用传二级商户号。 ");
155+
subOrders.add(subOrder);
156+
order.setSubOrders(subOrders);
157+
Map orderInfo = service.orderInfo(order);
158+
orderInfo.put("code", 0);
159+
return orderInfo;
160+
}
161+
162+
/**
163+
* 获取二维码图像
164+
* 二维码支付
165+
*
166+
* @return 二维码图像
167+
* @throws IOException IOException
168+
*/
169+
@RequestMapping(value = "toQrPay.jpg", produces = "image/jpeg;charset=UTF-8")
170+
public byte[] toWxQrPay() throws IOException {
171+
CombinePayOrder order = new CombinePayOrder();
172+
order.setTransactionType(WxTransactionType.COMBINE_NATIVE);
173+
order.setCombineOutTradeNo("合单商户订单号");
174+
//子单信息,最多50单.
175+
List<SubOrder> subOrders = new ArrayList<>();
176+
SubOrder subOrder = new SubOrder();
177+
subOrder.setMchid("子单商户号");
178+
subOrder.setAttach("附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。 ");
179+
//"子单金额,单位为分。 "
180+
subOrder.setAmount(new CombineAmount(131));
181+
subOrder.setOutTradeNo("子单商户订单号 ");
182+
subOrder.setDescription("商品描述");
183+
subOrder.setSubMchid("二级商户商户号,由微信支付生成并下发。服务商子商户的商户号,被合单方。直连商户不用传二级商户号。 ");
184+
subOrders.add(subOrder);
185+
order.setSubOrders(subOrders);
186+
187+
//获取对应的支付账户操作工具(可根据账户id)
188+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
189+
ImageIO.write(service.genQrPay(order), "JPEG", baos);
190+
return baos.toByteArray();
191+
}
192+
193+
/**
194+
* 获取二维码地址
195+
* 二维码支付
196+
*
197+
* @return 二维码图像
198+
* @throws IOException IOException
199+
*/
200+
@RequestMapping(value = "getQrPay.json")
201+
public String getQrPay() {
202+
CombinePayOrder order = new CombinePayOrder();
203+
order.setTransactionType(WxTransactionType.COMBINE_NATIVE);
204+
order.setCombineOutTradeNo("合单商户订单号");
205+
//子单信息,最多50单.
206+
List<SubOrder> subOrders = new ArrayList<>();
207+
SubOrder subOrder = new SubOrder();
208+
subOrder.setMchid("子单商户号");
209+
subOrder.setAttach("附加数据,在查询API和支付通知中原样返回,可作为自定义参数使用。1 ");
210+
//"子单金额,单位为分。 "
211+
subOrder.setAmount(new CombineAmount(115));
212+
subOrder.setOutTradeNo("子单商户订单号 ");
213+
subOrder.setDescription("商品描述");
214+
subOrder.setSubMchid("二级商户商户号,由微信支付生成并下发。服务商子商户的商户号,被合单方。直连商户不用传二级商户号。 ");
215+
subOrders.add(subOrder);
216+
order.setSubOrders(subOrders);
217+
//获取对应的支付账户操作工具(可根据账户id)
218+
return service.getQrPay(order);
219+
}
220+
221+
222+
/**
223+
* 支付回调地址
224+
*
225+
* @param request 请求
226+
* @return 是否成功
227+
* <p>
228+
* 业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
229+
* <p>
230+
* 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}
231+
* @throws IOException IOException
232+
*/
233+
@RequestMapping(value = "payBack.json")
234+
public String payBack(HttpServletRequest request) {
235+
//业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看com.egzosn.pay.common.api.PayService.setPayMessageHandler()
236+
return service.payBack(new HttpRequestNoticeParams(request)).toMessage();
237+
}
238+
239+
240+
/**
241+
* 查询
242+
*
243+
* @param order 订单的请求体
244+
* @return 返回查询回来的结果集,支付方原值返回
245+
*/
246+
@RequestMapping("query")
247+
public Map<String, Object> query(QueryOrder order) {
248+
return service.query(order.getTradeNo(), order.getOutTradeNo());
249+
}
250+
251+
252+
/**
253+
* 交易关闭接口
254+
*
255+
* @return 返回支付方交易关闭后的结果
256+
*/
257+
@RequestMapping("close")
258+
public Map<String, Object> close() {
259+
CombineCloseOrder order = new CombineCloseOrder();
260+
order.setOutTradeNo("合单商户订单号");
261+
//子单信息,最多50单.
262+
List<CombineSubOrder> subOrders = new ArrayList<>();
263+
CombineSubOrder subOrder = new CombineSubOrder();
264+
subOrder.setMchid("子单商户号");
265+
subOrder.setOutTradeNo("子单商户订单号 ");
266+
subOrder.setSubMchid("二级商户商户号,由微信支付生成并下发。服务商子商户的商户号,被合单方。直连商户不用传二级商户号。 ");
267+
subOrders.add(subOrder);
268+
order.setSubOrders(subOrders);
269+
return service.close(order);
270+
}
271+
272+
/**
273+
* 申请退款接口
274+
*
275+
* @param order 订单的请求体
276+
* @return 返回支付方申请退款后的结果
277+
*/
278+
@RequestMapping("refund")
279+
public WxRefundResult refund(RefundOrder order) {
280+
281+
return service.refund(order);
282+
}
283+
284+
/**
285+
* 查询退款
286+
*
287+
* @param order 订单的请求体
288+
* @return 返回支付方查询退款后的结果
289+
*/
290+
@RequestMapping("refundquery")
291+
public Map<String, Object> refundquery(RefundOrder order) {
292+
return service.refundquery(order);
293+
}
294+
295+
/**
296+
* 下载对账单
297+
*
298+
* @param order 订单的请求体
299+
* @return 返回支付方下载对账单的结果
300+
*/
301+
@RequestMapping("downloadbill")
302+
public Object downloadBill(QueryOrder order) {
303+
return service.downloadBill(order.getBillDate(), order.getBillType());
304+
}
305+
306+
307+
}

0 commit comments

Comments
 (0)