|
| 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 | +} |
0 commit comments