|
| 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