123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390 |
- package com.kmall.api.api;
- import com.kmall.api.annotation.IgnoreAuth;
- import com.kmall.api.annotation.LoginUser;
- import com.kmall.common.constant.Dict;
- import com.kmall.api.dao.ApiOrderRefundMapper;
- import com.kmall.api.entity.*;
- import com.kmall.api.service.*;
- import com.kmall.api.service.pay.wxpay.WxPayPropertiesBuilder;
- import com.kmall.api.util.ApiBaseAction;
- import com.kmall.api.util.CommonUtil;
- import com.kmall.common.utils.CharUtil;
- import com.kmall.common.utils.Constant;
- import com.kmall.common.utils.MapUtils;
- import com.kmall.common.utils.XmlUtil;
- import com.kmall.common.utils.wechat.AESUtil;
- import com.kmall.common.utils.wechat.WechatRefundApiResult;
- import com.kmall.common.utils.wechat.WechatRefundNotifyResult;
- import com.kmall.common.utils.wechat.WechatUtil;
- import org.apache.log4j.Logger;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.web.bind.annotation.*;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.io.ByteArrayOutputStream;
- import java.io.InputStream;
- import java.math.BigDecimal;
- import java.util.*;
- /**
- * 作者: @author Scott <br>
- * 时间: 2017-08-11 08:32<br>
- * 描述: ApiIndexController <br>
- */
- @RestController
- @RequestMapping("/api/pay")
- public class ApiPayController extends ApiBaseAction {
- private Logger logger = Logger.getLogger(ApiPayController.class);
- @Autowired
- private ApiOrderService orderService;
- @Autowired
- private ApiOrderGoodsService orderGoodsService;
- @Autowired
- private ApiPayService apiPayService;
- @Autowired
- private ApiOrderProcessRecordService orderProcessRecordService;
- @Autowired
- private ApiOrderExceptionRecordService apiOrderExceptionRecordService;
- @Autowired
- private ApiOrderRefundMapper mallOrderRefundMapper;
- /**
- */
- @RequestMapping("index")
- public Object index(@LoginUser UserVo loginUser) {
- return toResponsSuccess("");
- }
- /**
- * 获取支付的请求参数,用户生成订单, 商户订单号、预支付编号,且支付状态、订单状态均为支付中;
- */
- @GetMapping("pay_prepay")
- public Object payPrepay(@LoginUser UserVo loginUser, Long[] orderIds,String isMergePay) {
- List<Long> orderIdList=new ArrayList<>();
- String merchOrderSn = "";
- for(int i=0;i<orderIds.length;i++){
- orderIdList.add(orderIds[i]);
- }
- BigDecimal actual_price = Constant.ZERO;
- List<OrderVo> orderVoList = orderService.queryObjectByIdList(orderIdList);
- List<OrderProcessRecordEntity> processRecordEntityList = new ArrayList<>();
- for (OrderVo orderInfo:orderVoList) {
- if (orderInfo.getOrder_status() == 101) {
- return toResponsObject(400, "订单号为"+orderInfo.getOrder_sn()+"的订单超时支付,已取消", "");
- }
- if (orderInfo.getPay_status() != 0 && orderInfo.getPay_status() != 1) {
- return toResponsObject(400, "订单号为"+orderInfo.getOrder_sn()+"的订单已支付,请不要重复操作", "");
- }
- merchOrderSn = orderInfo.getMerchOrderSn();
- //如此次是单笔支付,则判断下单时该商户订单是否是拆单订单,如果都满足,则更新商户订单号,生成新的预支付信息
- if(Dict.isMergePay.item_0.getItem().equalsIgnoreCase(isMergePay)) {
- if ("2".equalsIgnoreCase(orderInfo.getIsMergePay())) {//多笔订单单笔支付,则商户订单号,生成新的预支付信息
- // merchOrderSn = "EMATO" + new SimpleDateFormat("yyyyMMddhhmmss").format(new Date());
- merchOrderSn = "EMATO"+ CommonUtil.generateOrderNumber();
- orderInfo.setMerchOrderSn(merchOrderSn);
- }
- }
- OrderProcessRecordEntity processRecordEntity = orderProcessRecordService.queryObjectByOrderSn(orderInfo.getOrder_sn());
- if(processRecordEntity != null){
- OrderProcessRecordEntity entity = new OrderProcessRecordEntity();
- entity.setOrderSn(orderInfo.getOrder_sn());
- entity.setUserId(Integer.valueOf(loginUser.getId()+""));
- entity.setPayStartTime(new Date());
- entity.setId(processRecordEntity.getId());
- processRecordEntityList.add(entity);
- }
- actual_price = actual_price.add(orderInfo.getActual_price());
- }
- String nonceStr = CharUtil.getRandomString(32);
- //https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=7_7&index=3
- Map<Object, Object> resultObj = new HashMap();
- try {
- Map<Object, Object> parame = new TreeMap<>();
- //parame.put("appid", ResourceUtil.getConfigByName("wx.appId"));
- parame.put("appid", WxPayPropertiesBuilder.instance().getAppId());
- //parame.put("mch_id", ResourceUtil.getConfigByName("wx.mchId"));// 商家账号。
- parame.put("mch_id", WxPayPropertiesBuilder.instance().getMchId());// 商家账号。
- String randomStr = CharUtil.getRandomNum(18).toUpperCase();
- parame.put("nonce_str", randomStr);// 随机字符串
- parame.put("out_trade_no", merchOrderSn);// 商户订单编号
- parame.put("body", "商城-支付");// 商品描述
- //订单的商品
- List<OrderGoodsVo> orderGoods = orderGoodsService.queryListByIds(orderIdList);
- if (null != orderGoods) {
- String body = "商城-";
- for (OrderGoodsVo goodsVo : orderGoods) {
- body = body + goodsVo.getGoods_name() + "、";
- }
- if (body.length() > 0) {
- body = body.substring(0, body.length() - 1);
- }
- parame.put("body", body);// 商品描述
- }
- //支付金额
- // parame.put("total_fee", orderInfo.getActual_price().multiply(Constant.ONE_HUNDRED).intValue()));//todo 消费金额
- parame.put("total_fee", actual_price.multiply(Constant.ONE_HUNDRED).intValue());// 消费金额
- //parame.put("notify_url", ResourceUtil.getConfigByName("wx.notifyUrl"));// 回调地址
- parame.put("notify_url", WxPayPropertiesBuilder.instance().getNotifyUrl());// 回调地址
- //parame.put("trade_type", ResourceUtil.getConfigByName("wx.tradeType"));// 交易类型APP
- parame.put("trade_type", WxPayPropertiesBuilder.instance().getTradeType());// 交易类型APP
- // parame.put("spbill_create_ip", getClientIp());
- //parame.put("spbill_create_ip", ResourceUtil.getConfigByName("spbillCreateIp"));
- parame.put("spbill_create_ip", WxPayPropertiesBuilder.instance().getSpbillCreateIp());
- parame.put("openid", loginUser.getWeixin_openid());
- // parame.put("sign_type", "MD5");
- //String sign = WechatUtil.arraySign(parame, ResourceUtil.getConfigByName("wx.paySignKey"));
- String sign = WechatUtil.arraySign(parame, WxPayPropertiesBuilder.instance().getPaySignKey());
- parame.put("sign", sign);// 数字签证
- String xml = MapUtils.convertMap2Xml(parame);
- logger.info("xml:" + xml);
- //Map<String, Object> resultUn = XmlUtil.xmlStrToMap(WechatUtil.requestOnce(ResourceUtil.getConfigByName("wx.uniformorder"), xml));
- Map<String, Object> resultUn = XmlUtil.xmlStrToMap(WechatUtil.requestOnce(WxPayPropertiesBuilder.instance().getUniformorder(), xml));
- // 响应报文
- String return_code = MapUtils.getString("return_code", resultUn);
- String return_msg = MapUtils.getString("return_msg", resultUn);
- //
- if (return_code.equalsIgnoreCase("FAIL")) {
- updateFailProcessBatch(processRecordEntityList, "支付失败," +return_msg);//更新订单流转信息
- addOrderExceptionRecord(orderVoList, Dict.exceptionStatus.item_00.getItem(),"支付失败," +return_msg);//记录订单异常信息
- return toResponsFail("支付失败," + return_msg);
- } else if (return_code.equalsIgnoreCase(WechatUtil.WXTradeState.SUCCESS.getCode())) {
- // 返回数据
- String result_code = MapUtils.getString("result_code", resultUn);
- String err_code_des = MapUtils.getString("err_code_des", resultUn);
- if (result_code.equalsIgnoreCase("FAIL")) {
- updateFailProcessBatch(processRecordEntityList, "支付失败," +err_code_des);//更新订单流转信息
- addOrderExceptionRecord(orderVoList, Dict.exceptionStatus.item_00.getItem(),"支付失败," +err_code_des);//记录订单异常信息
- return toResponsFail("支付失败," + err_code_des);
- } else if (result_code.equalsIgnoreCase(WechatUtil.WXTradeState.SUCCESS.getCode())) {
- apiPayService.payPrepay(resultObj, resultUn, nonceStr, orderVoList);
- orderProcessRecordService.updateBatch(processRecordEntityList);//更新订单流转信息
- return toResponsObject(0, "微信统一订单下单成功", resultObj);
- }
- }
- } catch (Exception e) {
- e.printStackTrace();
- updateFailProcessBatch(processRecordEntityList, "下单失败,error=" + e.getMessage());//更新订单流转信息
- return toResponsFail("下单失败,error=" + e.getMessage());
- }
- return toResponsFail("下单失败");
- }
- /**
- * 更新订单支付失败流转信息
- * @param processRecordEntityList
- * @param return_msg
- */
- public void updateFailProcessBatch(List<OrderProcessRecordEntity> processRecordEntityList,String return_msg){
- for (OrderProcessRecordEntity orderProcessRecordEntity : processRecordEntityList) {
- orderProcessRecordEntity.setIsPaymentSend(Dict.isSend.item_0.getItem());
- orderProcessRecordEntity.setProcessContent(return_msg);
- }
- orderProcessRecordService.updateBatch(processRecordEntityList);
- }
- /**
- * 记录订单异常信息
- * @param orderVoList
- * @param exceptionStatus
- * @param expContent
- */
- public void addOrderExceptionRecord(List<OrderVo> orderVoList,String exceptionStatus,String expContent){
- for (OrderVo orderInfo: orderVoList) {
- MallOrderExceptionRecord mallOrderExceptionRecord = new MallOrderExceptionRecord();
- mallOrderExceptionRecord.setUserId(Integer.parseInt(orderInfo.getUser_id()+""));
- mallOrderExceptionRecord.setOrderSn(orderInfo.getOrder_sn());
- mallOrderExceptionRecord.setExceptionStatus(exceptionStatus);
- mallOrderExceptionRecord.setExceptionContent(expContent);
- mallOrderExceptionRecord.setCreateTime(new Date());
- apiOrderExceptionRecordService.save(mallOrderExceptionRecord);
- }
- }
- /**
- * 微信订单回调接口
- *
- * @return
- */
- @IgnoreAuth
- @RequestMapping(value = "/notify", produces = "text/html;charset=UTF-8")
- @ResponseBody
- public void notify(HttpServletRequest request, HttpServletResponse response) {
- logger.info("微信订单回调接口>>>>>>notify start");
- try {
- request.setCharacterEncoding("UTF-8");
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/html;charset=UTF-8");
- response.setHeader("Access-Control-Allow-Origin", "*");
- InputStream in = request.getInputStream();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int len = 0;
- while ((len = in.read(buffer)) != -1) {
- out.write(buffer, 0, len);
- }
- out.close();
- in.close();
- String reponseXml = new String(out.toByteArray(), "utf-8");//xml数据
- logger.error("reponseXml:" + reponseXml);
- WechatRefundApiResult result = (WechatRefundApiResult) XmlUtil.xmlStrToBean(reponseXml, WechatRefundApiResult.class);
- String result_code = result.getResult_code();
- if (result_code.equalsIgnoreCase("FAIL")) {
- String out_trade_no = result.getOut_trade_no();//订单编号
- logger.error("订单" + out_trade_no + "支付失败");
- response.getWriter().write(setXml("SUCCESS", "OK"));
- response.getWriter().close();
- } else if (result_code.equalsIgnoreCase(WechatUtil.WXTradeState.SUCCESS.getCode())) {
- //验签
- String time_end = result.getTime_end();
- String out_trade_no = result.getOut_trade_no();//商户订单号
- String transaction_id = result.getTransaction_id();//微信支付订单号
- String total_fee = result.getTotal_fee();//订单编号
- logger.error("订单" + out_trade_no + "支付成功");
- // 业务处理
- apiPayService.notify(out_trade_no,total_fee,transaction_id,time_end);
- response.getWriter().write(setXml("SUCCESS", "OK"));
- }
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
- }
- /**
- * 订单退款请求 todo 小程序用户暂不给退款
- */
- /*@GetMapping("refund")
- public Object refund(@LoginUser UserVo loginUser, Long orderId) {
- //
- OrderVo orderInfo = orderService.queryObject(orderId);
- if (null == orderInfo) {
- return toResponsObject(400, "订单已取消", "");
- }
- if (orderInfo.getOrder_status() == 401 || orderInfo.getOrder_status() == 402) {
- return toResponsObject(400, "订单已退款", "");
- }
- if (orderInfo.getPay_status() != 2) {
- return toResponsObject(400, "订单未付款,不能退款", "");
- }
- // WechatRefundApiResult result = WechatUtil.wxRefund(orderInfo.getId().toString(),
- // orderInfo.getActual_price().doubleValue(), orderInfo.getActual_price().doubleValue());
- WechatRefundApiResult result = WechatUtil.wxRefund(orderInfo.getMerchOrderSn().toString(),
- orderInfo.getActual_price().doubleValue(), orderInfo.getActual_price().doubleValue());
- if (result.getResult_code().equals("SUCCESS")) {
- apiPayService.refund(orderInfo,result,"");
- return toResponsObject(400, "成功退款", "");
- } else {
- MallOrderRefund mallOrderRefund = mallOrderRefundMapper.queryObjectByOrderId(orderInfo.getId()+"");
- MallOrderRefund orderRefund = new MallOrderRefund();
- orderRefund.setRefundType(Integer.parseInt(Dict.RefundType.item_1.getItem()));
- orderRefund.setRefundMoney(BigDecimal.valueOf(orderInfo.getActual_price().multiply(Constant.ONE_HUNDRED).doubleValue()));
- orderRefund.setRefundStatus(Integer.parseInt(Dict.RefundStatus.item_3.getItem()));
- orderRefund.setModTime(new Date());
- if(mallOrderRefund !=null){
- orderRefund.setId(mallOrderRefund.getId());
- mallOrderRefundMapper.update(orderRefund);
- }
- MallOrderExceptionRecord mallOrderExceptionRecord = new MallOrderExceptionRecord();
- mallOrderExceptionRecord.setUserId(Integer.parseInt(orderInfo.getUser_id()+""));
- mallOrderExceptionRecord.setOrderSn(orderInfo.getOrder_sn());
- mallOrderExceptionRecord.setExceptionStatus(Dict.exceptionStatus.item_03.getItem());
- mallOrderExceptionRecord.setExceptionContent("退款失败"+result.getErr_code_des());
- mallOrderExceptionRecord.setCreateTime(new Date());
- apiOrderExceptionRecordService.save(mallOrderExceptionRecord);
- return toResponsObject(400, "退款失败"+result.getErr_code_des(), "");
- }
- }*/
- /**
- * 微信订单退款回调接口
- *
- * @return
- */
- @IgnoreAuth
- @RequestMapping(value = "/refundNotify", produces = "text/html;charset=UTF-8")
- @ResponseBody
- public void refundNotify(HttpServletRequest request, HttpServletResponse response) {
- logger.error("refundNotify start");
- try {
- request.setCharacterEncoding("UTF-8");
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/html;charset=UTF-8");
- response.setHeader("Access-Control-Allow-Origin", "*");
- InputStream in = request.getInputStream();
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- byte[] buffer = new byte[1024];
- int len = 0;
- while ((len = in.read(buffer)) != -1) {
- out.write(buffer, 0, len);
- }
- out.close();
- in.close();
- String reponseXml = new String(out.toByteArray(), "utf-8");//xml数据
- logger.error("reponseXml:" + reponseXml);
- WechatRefundNotifyResult result = (WechatRefundNotifyResult) XmlUtil.xmlStrToBean(reponseXml, WechatRefundNotifyResult.class);
- if (result.getReturn_code().equalsIgnoreCase("FAIL")) {
- logger.info("微信查询接口调用失败: "+result.getReturn_msg());
- response.getWriter().write(setXml("SUCCESS", "OK"));
- response.getWriter().close();
- }else {
- String req_info = result.getReq_info();//加密信息
- String aesResult = AESUtil.decryptData(req_info);
- System.out.println(aesResult);
- WechatRefundApiResult refundApiResult = (WechatRefundApiResult) XmlUtil.xmlStrToBean(aesResult, WechatRefundApiResult.class);
- logger.error("订单" + refundApiResult.getOut_trade_no() + "退款成功");
- // 业务处理
- apiPayService.refundNotify(refundApiResult);
- response.getWriter().write(setXml("SUCCESS", "OK"));
- }
- } catch (Exception e) {
- e.printStackTrace();
- return;
- }
- }
- /**
- * 订单退款请求
- */
- @IgnoreAuth
- @GetMapping("test")
- public Object test(Long orderId) {
- OrderVo orderInfo = orderService.queryObject(orderId);
- // 微信通知
- orderService.notifyPaySuccess(orderInfo);
- return null;
- }
- //返回微信服务
- public static String setXml(String return_code, String return_msg) {
- return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
- }
- //模拟微信回调接口
- public static String callbakcXml(String orderNum) {
- return "<xml><appid><![CDATA[wx2421b1c4370ec43b]]></appid><attach><![CDATA[支付测试]]></attach><bank_type><![CDATA[CFT]]></bank_type><fee_type><![CDATA[CNY]]></fee_type> <is_subscribe><![CDATA[Y]]></is_subscribe><mch_id><![CDATA[10000100]]></mch_id><nonce_str><![CDATA[5d2b6c2a8db53831f7eda20af46e531c]]></nonce_str><openid><![CDATA[oUpF8uMEb4qRXf22hE3X68TekukE]]></openid> <out_trade_no><![CDATA[" + orderNum + "]]></out_trade_no> <result_code><![CDATA[SUCCESS]]></result_code> <return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[B552ED6B279343CB493C5DD0D78AB241]]></sign><sub_mch_id><![CDATA[10000100]]></sub_mch_id> <time_end><![CDATA[20140903131540]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[JSAPI]]></trade_type><transaction_id><![CDATA[1004400740201409030005092168]]></transaction_id></xml>";
- }
- }
|