Skip to content

Commit 9b82bca

Browse files
committed
分账功能实现
1 parent 973a469 commit 9b82bca

2 files changed

Lines changed: 293 additions & 0 deletions

File tree

Lines changed: 264 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,264 @@
1+
2+
package com.egzosn.pay.demo.controller;
3+
4+
5+
import java.io.IOException;
6+
import java.math.BigDecimal;
7+
import java.util.ArrayList;
8+
import java.util.List;
9+
import java.util.Map;
10+
11+
import javax.annotation.PostConstruct;
12+
import javax.servlet.http.HttpServletRequest;
13+
14+
import org.springframework.web.bind.annotation.RequestMapping;
15+
import org.springframework.web.bind.annotation.RestController;
16+
17+
import com.egzosn.pay.common.bean.AssistOrder;
18+
import com.egzosn.pay.common.bean.CertStoreType;
19+
import com.egzosn.pay.common.bean.RefundResult;
20+
import com.egzosn.pay.demo.request.QueryOrder;
21+
import com.egzosn.pay.demo.service.handler.WxV3ProfitSharingMessageHandler;
22+
import com.egzosn.pay.web.support.HttpRequestNoticeParams;
23+
import com.egzosn.pay.wx.v3.api.WxPayConfigStorage;
24+
import com.egzosn.pay.wx.v3.api.WxProfitSharingService;
25+
import com.egzosn.pay.wx.v3.bean.WxProfitSharingTransactionType;
26+
import com.egzosn.pay.wx.v3.bean.sharing.ProfitSharingBillType;
27+
import com.egzosn.pay.wx.v3.bean.sharing.ProfitSharingOrder;
28+
import com.egzosn.pay.wx.v3.bean.sharing.ProfitSharingReturnOrder;
29+
import com.egzosn.pay.wx.v3.bean.sharing.Receiver;
30+
import com.egzosn.pay.wx.v3.bean.sharing.ReceiverType;
31+
import com.egzosn.pay.wx.v3.bean.sharing.ReceiversOrder;
32+
import com.egzosn.pay.wx.v3.bean.sharing.RelationType;
33+
34+
/**
35+
* 微信V3分账发起支付入口
36+
*
37+
* @author egan
38+
* email egzosn@gmail.com
39+
* date 2016/11/18 0:25
40+
*/
41+
@RestController
42+
@RequestMapping("wxV3profitSharing")
43+
public class WxV3ProfitSharingController {
44+
45+
private WxProfitSharingService service = null;
46+
47+
@PostConstruct //没有证书的情况下注释掉,避免启动报错
48+
public void init() {
49+
WxPayConfigStorage wxPayConfigStorage = new WxPayConfigStorage();
50+
wxPayConfigStorage.setAppId("wxc7b993ff15a9f26c");
51+
wxPayConfigStorage.setMchId("1602947765");
52+
//V3密钥 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_2.shtml
53+
wxPayConfigStorage.setV3ApiKey("9bd8f0e7af4841299d782406b7774f57");
54+
wxPayConfigStorage.setNotifyUrl("http://sailinmu.iok.la/wxV3profitSharing/payBack.json");
55+
wxPayConfigStorage.setReturnUrl("http://sailinmu.iok.la/wxV3profitSharing/payBack.json");
56+
wxPayConfigStorage.setInputCharset("utf-8");
57+
//使用证书时设置为true
58+
wxPayConfigStorage.setCertSign(true);
59+
//商户API证书 https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml
60+
wxPayConfigStorage.setApiClientKeyP12("yifenli_mall.p12");
61+
wxPayConfigStorage.setCertStoreType(CertStoreType.PATH);
62+
service = new WxProfitSharingService(wxPayConfigStorage);
63+
//设置回调消息处理
64+
//TODO {@link com.egzosn.pay.demo.controller.WxPayController#payBack}
65+
service.setPayMessageHandler(new WxV3ProfitSharingMessageHandler());
66+
}
67+
68+
69+
/**
70+
* 请求分账API
71+
*
72+
* @return 分账
73+
*/
74+
@RequestMapping(value = "orders")
75+
public Map<String, Object> orders() {
76+
ProfitSharingOrder order = new ProfitSharingOrder();
77+
order.setTransactionType(WxProfitSharingTransactionType.ORDERS);
78+
order.setSubMchid("服务商必填----微信支付分配的子商户号,即分账的出资商户号。");
79+
order.setSubAppid("服务商必填----微信分配的子商户公众账号ID,分账接收方类型包含PERSONAL_SUB_OPENID时必填。");
80+
order.setTransactionId("微信支付订单号");
81+
order.setOutOrderNo("务商系统内部的分账单号,在服务商系统内部唯一,同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@ ");
82+
List<Receiver> receivers = new ArrayList<>();
83+
Receiver receiver = new Receiver();
84+
//1、MERCHANT_ID:商户号
85+
//2、PERSONAL_OPENID:个人openid(由父商户APPID转换得到)
86+
//3、PERSONAL_SUB_OPENID: 个人sub_openid(由子商户APPID转换得到)
87+
//示例值:MERCHANT_ID
88+
receiver.setType(ReceiverType.MERCHANT_ID);
89+
receiver.setName("分账个人接收方姓名");
90+
receiver.setAccount("分账接收方账号");
91+
//分账金额,单位为分,只能为整数,不能超过原订单支付金额及最大分账比例金额
92+
receiver.setAmount(1);
93+
receiver.setDescription("分账的原因描述,分账账单中需要体现");
94+
95+
order.setReceivers(receivers);
96+
//1、如果为true,该笔订单剩余未分账的金额会解冻回分账方商户;
97+
//2、如果为false,该笔订单剩余未分账的金额不会解冻回分账方商户,可以对该笔订单再次进行分账。
98+
order.setUnfreezeUnsplit(true);
99+
Map<String, Object> orderInfo = service.orderInfo(order);
100+
orderInfo.put("code", 0);
101+
return orderInfo;
102+
}
103+
104+
105+
/**
106+
* 获取支付预订单信息
107+
*
108+
* @return 支付预订单信息
109+
*/
110+
@RequestMapping("unfreeze")
111+
public Map<String, Object> unfreeze() {
112+
ProfitSharingOrder order = new ProfitSharingOrder();
113+
order.setTransactionType(WxProfitSharingTransactionType.ORDERS_UNFREEZE);
114+
order.setSubMchid("服务商必填----微信支付分配的子商户号,即分账的出资商户号。");
115+
order.setTransactionId("微信支付订单号");
116+
order.setOutOrderNo("务商系统内部的分账单号,在服务商系统内部唯一,同一分账单号多次请求等同一次。只能是数字、大小写字母_-|*@ ");
117+
order.setSubject("分账的原因描述,分账账单中需要体现");
118+
return service.orderInfo(order);
119+
}
120+
/**
121+
* 添加分账接收方
122+
*
123+
* @return 添加分账接收方
124+
*/
125+
@RequestMapping("add")
126+
public Map<String, Object> add() {
127+
ReceiversOrder order = new ReceiversOrder();
128+
order.setTransactionType(WxProfitSharingTransactionType.RECEIVERS_ADD);
129+
order.setSubMchid("服务商必填----微信支付分配的子商户号,即分账的出资商户号。");
130+
order.setSubAppid("服务商必填----子商户应用ID");
131+
//分账接收方类型:
132+
order.setType(ReceiverType.MERCHANT_ID);
133+
order.setAccount("分账接收方账号");
134+
order.setName("分账个人接收方姓名");
135+
//与分账方的关系类型
136+
order.setRelationType(RelationType.BRAND);
137+
order.setCustomRelation("自定义的分账关系,子商户与接收方具体的关系,本字段最多10个字。\n" +
138+
"当字段relation_type的值为CUSTOM时,本字段必填;\n" +
139+
"当字段relation_type的值不为CUSTOM时,本字段无需填写");
140+
return service.orderInfo(order);
141+
}
142+
/**
143+
* 删除分账接收方
144+
*
145+
* @return 删除分账接收方
146+
*/
147+
@RequestMapping("delete")
148+
public Map<String, Object> delete() {
149+
ReceiversOrder order = new ReceiversOrder();
150+
order.setTransactionType(WxProfitSharingTransactionType.RECEIVERS_DELETE);
151+
order.setSubMchid("服务商必填----微信支付分配的子商户号,即分账的出资商户号。");
152+
order.setSubAppid("服务商必填----子商户应用ID");
153+
//分账接收方类型:
154+
order.setType(ReceiverType.MERCHANT_ID);
155+
order.setAccount("分账接收方账号");
156+
157+
158+
return service.orderInfo(order);
159+
}
160+
161+
162+
/**
163+
* 分账回调地址
164+
*
165+
* @param request 请求
166+
* @return 是否成功
167+
* <p>
168+
* 业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看{@link com.egzosn.pay.common.api.PayService#setPayMessageHandler(com.egzosn.pay.common.api.PayMessageHandler)}
169+
* <p>
170+
* 如果未设置 {@link com.egzosn.pay.common.api.PayMessageHandler} 那么会使用默认的 {@link com.egzosn.pay.common.api.DefaultPayMessageHandler}
171+
* @throws IOException IOException
172+
*/
173+
@RequestMapping(value = "payBack.json")
174+
public String payBack(HttpServletRequest request) {
175+
//业务处理在对应的PayMessageHandler里面处理,在哪里设置PayMessageHandler,详情查看com.egzosn.pay.common.api.PayService.setPayMessageHandler()
176+
return service.payBack(new HttpRequestNoticeParams(request)).toMessage();
177+
}
178+
179+
180+
/**
181+
* 查询分账结果
182+
*
183+
* @return 返回查询回来的结果集,支付方原值返回
184+
*/
185+
@RequestMapping("query")
186+
public Map<String, Object> query() {
187+
AssistOrder assistOrder = new AssistOrder();
188+
assistOrder.setOutTradeNo("商户分账单号");
189+
assistOrder.setTradeNo("微信订单号");
190+
assistOrder.addAttr("sub_mchid", "服务商必填---子商户号");
191+
return service.query(assistOrder);
192+
}
193+
194+
195+
/**
196+
* 查询剩余待分金额
197+
*
198+
* @return 返回查询回来的结果集,支付方原值返回
199+
*/
200+
@RequestMapping("amounts")
201+
public Map<String, Object> amounts() {
202+
AssistOrder assistOrder = new AssistOrder();
203+
assistOrder.setTradeNo("微信订单号");
204+
return service.query(assistOrder);
205+
}
206+
207+
208+
/**
209+
* 查询最大分账比例
210+
* 服务商使用
211+
* @return 返回查询回来的结果集,支付方原值返回
212+
*/
213+
@RequestMapping("merchantConfigs")
214+
public Map<String, Object> merchantConfigs() {
215+
AssistOrder assistOrder = new AssistOrder();
216+
assistOrder.addAttr("sub_mchid", "服务商必填---子商户号");
217+
return service.query(assistOrder);
218+
}
219+
220+
/**
221+
* 请求分账回退
222+
*
223+
* @return 返回支付方申请退款后的结果
224+
*/
225+
@RequestMapping("refund")
226+
public RefundResult refund() {
227+
ProfitSharingReturnOrder returnOrder = new ProfitSharingReturnOrder();
228+
returnOrder.setSubMchid("服务商必填---子商户号");
229+
returnOrder.setRefundNo("商户回退单号");
230+
returnOrder.setTradeNo("微信分账单号");
231+
returnOrder.setOutTradeNo("商户分账单号");
232+
returnOrder.setRefundAmount(new BigDecimal(1));
233+
234+
returnOrder.setDescription("分账回退的原因描述");
235+
return service.refund(returnOrder);
236+
}
237+
238+
/**
239+
* 查询分账回退结果
240+
*
241+
* @return 返回支付方查询退款后的结果
242+
*/
243+
@RequestMapping("refundquery")
244+
public Map<String, Object> refundquery() {
245+
ProfitSharingReturnOrder returnOrder = new ProfitSharingReturnOrder();
246+
returnOrder.setSubMchid("服务商必填---子商户号");
247+
returnOrder.setRefundNo("商户回退单号");
248+
returnOrder.setOutTradeNo("商户分账单号");
249+
return service.refundquery(returnOrder);
250+
}
251+
252+
/**
253+
* 下载对账单
254+
*
255+
* @param order 订单的请求体
256+
* @return 返回支付方下载对账单的结果
257+
*/
258+
@RequestMapping("downloadbill")
259+
public Object downloadBill(QueryOrder order) {
260+
return service.downloadBill(order.getBillDate(), ProfitSharingBillType.GZIP);
261+
}
262+
263+
264+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.egzosn.pay.demo.service.handler;
2+
3+
import java.util.Map;
4+
5+
import org.slf4j.Logger;
6+
import org.slf4j.LoggerFactory;
7+
8+
import com.alibaba.fastjson.JSON;
9+
import com.egzosn.pay.common.api.DefaultPayMessageHandler;
10+
import com.egzosn.pay.common.api.PayMessageHandler;
11+
import com.egzosn.pay.common.api.PayService;
12+
import com.egzosn.pay.common.bean.PayOutMessage;
13+
import com.egzosn.pay.common.exception.PayErrorException;
14+
import com.egzosn.pay.wx.v3.bean.sharing.ProfitSharingPayMessage;
15+
16+
/**
17+
* 微信合单支付回调处理器
18+
* Created by ZaoSheng on 2016/6/1.
19+
*/
20+
public class WxV3ProfitSharingMessageHandler implements PayMessageHandler<ProfitSharingPayMessage, PayService> {
21+
22+
private final Logger LOG = LoggerFactory.getLogger(DefaultPayMessageHandler.class);
23+
24+
@Override
25+
public PayOutMessage handle(ProfitSharingPayMessage payMessage, Map<String, Object> context, PayService payService) throws PayErrorException {
26+
LOG.info("回调支付消息处理器,回调消息:{}", JSON.toJSONString(payMessage));
27+
return payService.successPayOutMessage(payMessage);
28+
}
29+
}

0 commit comments

Comments
 (0)