美文网首页
微信支付

微信支付

作者: 小别墅是毛坯 | 来源:发表于2020-01-09 14:45 被阅读0次
app.id=wx2ff
app.secret=2fd0d010
token=debe817e7
#公众号网页授权
oauth.url=http://api.china-start.cn-api/oauth
oauth.redirect.url=http://api.china-start.cn/shop-api
#JSAPI支付配置
mch.id=148392
order.notify.url=http://pi/order/notify
luckyorder.notify.url=http://api.china-start.cn/shop-api/lucky/notify
deposit.notify.url=http://api./deposit/notify
pay.secret=7dc985d317d5ea2b
life.order.notify.url=http://life/order/notify
hotel.order.notify.url=http://rchant/hotel/order/notify
@Data
@ApiModel("订单支付信息-调起支付")
public class OrderPayDto implements Serializable {

  @ApiModelProperty("微信公众号appId")
  private String appId;

  @ApiModelProperty("时间戳")
  private String timeStamp;

  @ApiModelProperty("随机字符串")
  private String nonceStr;

  @ApiModelProperty("支付信息")
  @JsonProperty("package")
  private String packageStr;

  @ApiModelProperty("签名类型")
  private String signType;

  @ApiModelProperty("支付签名")
  private String paySign;
}

  @ApiOperation(value = "订单支付回调通知", notes = "订单支付回调通知", hidden = true)
    @PostMapping(value = "/notify")
    @Authority(AuthorityEnum.NOCHECK)
    public String payNotify() {
        boolean checkFlag = false;
        try {
            String notifyInfo = RequestUtil.parseWechatNotifyParams(request);
            checkFlag = WechatPayUtil.checkCallBackWechatPaySign(notifyInfo);

            if (checkFlag) {
                checkFlag = orderService.updatePayStatus(notifyInfo);
                //模板消息通知(通知用户-购物成功、通知商户-新订单)
                if (checkFlag) {
                    orderService.wechatTemplateNotify(notifyInfo);
                }
            }
        } catch (IOException | DocumentException e) {
            e.printStackTrace();
        }
        return WechatPayUtil.generateWxCallBackResponse(checkFlag);
    }
 /**
     * 解析微信回调通知参数(简单封装,仅限微信回调用)
     *
     * @param request request
     * @return 微信回调通知参数
     * @throws IOException e
     */
    public static String parseWechatNotifyParams(HttpServletRequest request) throws IOException {
        BufferedReader in = new BufferedReader(new InputStreamReader(request.getInputStream(), StandardCharsets.UTF_8));
        StringBuilder sb = new StringBuilder();
        String line;
        while ((line = in.readLine()) != null) {
            sb.append(line);
        }
        in.close();
        return sb.toString();
    }
    /**
     * 订单支付-用户下单
     *
     * @param userId     用户ID
     * @param orderPayNo 订单支付单号
     * @param clientIp   客户端IP
     * @return 公众号支付参数
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderPayDto orderPay(Integer userId, String orderPayNo, String clientIp) {
        User user = userService.getUserInfo(userId);
        GoodsPayOrder goodsPayOrder = orderDao.getGoodsPayOrder(userId, orderPayNo);
        Map<String, String> payInfo = WechatPayUtil.fetchOrder("中广融媒数字科技", "中广融媒数字科技",
                goodsPayOrder.getTradeNo(), goodsPayOrder.getPayAmount(), clientIp, user.getOpenId(), WechatPayUtil.ORDER_NOTIFY_URL);
        //根据订单编号获取订单id
        GoodsOrder goodsOrder = goodsOrderMapper.selectByPrimaryKey(orderPayNo);
        //支付成功后修改基础销量信息
//        goodsMapper.updateSalesVolume(goodsOrder.getId());

        return JsonUtil.getInstance().toJsonObj(payInfo, OrderPayDto.class);
    }

    /**
     * 订单支付-订单列表
     *
     * @param userId   用户ID
     * @param orderId  订单支ID
     * @param clientIp 客户端IP
     * @return 公众号支付参数
     */
    @Transactional(rollbackFor = Exception.class)
    public OrderPayDto orderPay(Integer userId, Integer orderId, String clientIp) {
        User user = userService.getUserInfo(userId);
        GoodsOrder goodsOrder = orderDao.getGoodsOrderByStatus(userId, orderId, OrderStatusEnum.waitPay);
        AssertUtil.notNull(goodsOrder, ExceptionEnum.GoodsOrderInValid);

        //生成支付单信息
        String payOrderNo = DateUtils.getTimeString(DateUtils.DATE_YYYYMMDDHHMMSS, new Date()) + RandomStringUtils.randomNumeric(6);
        BigDecimal payAmount = goodsOrder.getPayAmount();

        boolean payOrderFlag = orderDao.addPayOrder(userId, 1, payOrderNo, payAmount);
        AssertUtil.isTrue(payOrderFlag, ExceptionEnum.OrderGoodsFail);

        //更新订单交易单号
        orderDao.updateGoodsOrderPayOrderNo(userId, payOrderNo, Lists.newArrayList(orderId));

        Map<String, String> payInfo = WechatPayUtil.fetchOrder("中广融媒数字科技", "中广融媒数字科技",
                payOrderNo, payAmount, clientIp, user.getOpenId(), WechatPayUtil.ORDER_NOTIFY_URL);

        return JsonUtil.getInstance().toJsonObj(payInfo, OrderPayDto.class);
    }

    /**
     * 支付回调-更新支付单、订单状态
     *
     * @param notifyInfo 支付回调信息
     * @return 回调处理结果
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean updatePayStatus(String notifyInfo) {
        //TODO 金额校验
        try {
            Map<String, String> params = XmlUtils.xmlStr2Map(notifyInfo);

            System.out.println(params);

            String payOrderNo = params.get("out_trade_no");
            String outTradeNo = params.get("transaction_id");

            boolean payStatus = orderDao.updatePayStatus(payOrderNo, outTradeNo);
            if (payStatus) {
                List<GoodsOrder> goodsOrders = orderDao.getGoodsOrder(payOrderNo);
                if (goodsOrders.size() == 1) {
                    GoodsOrder goodsOrder = goodsOrders.get(0);
                    Integer isGroup = goodsOrder.getIsGroup();
                    if (isGroup == null) {
                        isGroup = 0;
                    }
                    if (isGroup == 1) {
                        //拼团订单
                        groupService.excuteGroup(goodsOrder.getUserId(), goodsOrder.getId(), goodsOrder.getGroupId());
                    }
                }
            }
            return payStatus;
        } catch (DocumentException e) {
            e.printStackTrace();
        }

        return false;
    }
 ************************工具类***********************
public class WechatPayUtil {
    private static final PropertiesUtil WECHAT_PRO = new PropertiesUtil("/configs/wechat.properties");
    public static final String ORDER_NOTIFY_URL;
    public static final String LUCKYORDER_NOTIFY_URL; //奖券特殊回调地址
    public static final String DEPOSIT_NOTIFY_URL;
    public static final String LIFE_ORDER_NOTIFY_URL;
    public static final String HOTEL_ORDER_NOTIFY_URL;
    private static final String APP_ID;
    private static final String MCH_ID;
    private static final String PAY_SECRET;

    static {
        APP_ID = WECHAT_PRO.getProperty("app.id");
        MCH_ID = WECHAT_PRO.getProperty("mch.id");
        ORDER_NOTIFY_URL = WECHAT_PRO.getProperty("order.notify.url");
        LUCKYORDER_NOTIFY_URL = WECHAT_PRO.getProperty("luckyorder.notify.url");
        DEPOSIT_NOTIFY_URL = WECHAT_PRO.getProperty("deposit.notify.url");
        LIFE_ORDER_NOTIFY_URL = WECHAT_PRO.getProperty("life.order.notify.url");
        HOTEL_ORDER_NOTIFY_URL = WECHAT_PRO.getProperty("hotel.order.notify.url");
        PAY_SECRET = WECHAT_PRO.getProperty("pay.secret");
    }

    private static final String TRADE_STATUS_SUCCESS = "SUCCESS";

    /**
     * 微信JSAPI支付统一下单 预支付交易单 xml字符串
     *
     * @param body     商品简单描述
     * @param detail   商品详细描述
     * @param orderNo  内部订单号
     * @param money    订单金额 (单位: 元)
     * @param clientIp 客户端IP
     * @param openId   用户openId
     * @return 微信JSAPI支付预支付交易单 xml字符串
     */
    private static String generateUnifiedOrder(String body, String detail, @Nonnull String orderNo,
                                               @Nonnull BigDecimal money, String clientIp, @Nonnull String openId, @Nonnull String notifyUrl) {
        Map<String, String> params = Maps.newHashMap();
        params.put("appid", APP_ID);
        params.put("mch_id", MCH_ID);
        params.put("nonce_str", RandomStringUtils.randomAlphabetic(6));
        params.put("body", body);
        params.put("detail", detail);
        params.put("out_trade_no", orderNo);
        params.put("total_fee", money.multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_DOWN).toString());
        params.put("spbill_create_ip", clientIp);
        params.put("notify_url", notifyUrl);
        params.put("trade_type", "JSAPI");
        params.put("openid", openId);
        params.put("sign", generateWechatPaySign(params));

        return XmlUtils.map2XmlStr(MapUtils.mapParamOrderByAsc(params));
    }

    /**
     * 微信JSAPI支付统一下单
     *
     * @param goodsDesc   商品描述
     * @param goodsDetail 商品详情
     * @param orderNo     内部订单号
     * @param money       订单金额 (单位: 元)
     * @param clientIp    客户端IP
     * @param openId      用户openId
     * @return 客户端JSAPI支付参数
     */
    public static Map<String, String> fetchOrder(String goodsDesc, String goodsDetail, String orderNo,
                                                 BigDecimal money, String clientIp, String openId, String notifyUrl) {
        try {
            String unifiedOrder = generateUnifiedOrder(goodsDesc, goodsDetail, orderNo, money, clientIp, openId, notifyUrl);
            String unifiedOrderResult = HttpUtil.getResult(WechatConstant.UNIFIED_ORDER, unifiedOrder);
            Map<String, String> payResult = XmlUtils.xmlStr2Map(unifiedOrderResult);

            log.info(JsonUtil.getInstance().toJsonString(payResult));

            Map<String, String> payValue = Maps.newHashMap();
            payValue.put("appId", APP_ID);
            payValue.put("timeStamp", System.currentTimeMillis() / 1000 + "");
            payValue.put("nonceStr", RandomStringUtils.randomAlphabetic(6));
            payValue.put("package", "prepay_id=" + payResult.get("prepay_id"));
            payValue.put("signType", "MD5");
            payValue.put("paySign", generateWechatPaySign(payValue));

            return payValue;
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        throw new WebException(ExceptionEnum.Exception);
    }

    private static String generateWechatPaySign(Map<String, String> params) {
        String plainValue = MapUtils.mapParamOrderByAscJoinUrlDelimiter(params) + "&key=" + PAY_SECRET;
        return CodecUtil.getMD5Cryptography(plainValue).toUpperCase();
    }

    /**
     * 校验微信支付回调信息
     *
     * @param notifyInfo 微信支付回调信息
     * @return true/false
     */
    public static boolean checkCallBackWechatPaySign(String notifyInfo) throws DocumentException {
        Map<String, String> params = XmlUtils.xmlStr2Map(notifyInfo);
        String oldSignStr = params.get("sign");
        params.remove("sign");

        String newSignStr = generateWechatPaySign(params);
        if (!oldSignStr.equals(newSignStr)) {
            return false;
        }

        return StringUtils.equalsIgnoreCase(params.get("return_code"), TRADE_STATUS_SUCCESS) && StringUtils.equalsIgnoreCase(params.get("result_code"), TRADE_STATUS_SUCCESS);
    }

    /**
     * 生成微信支付回调响应信息
     *
     * @param checkFlag 签名校验结果
     * @return 微信支付回调响应信息
     */
    public static String generateWxCallBackResponse(boolean checkFlag) {
        Map<String, String> params = Maps.newHashMap();
        String returnCode = "FAIL";
        String returnMsg = "校验签名失败";
        if (checkFlag) {
            returnCode = "SUCCESS";
            returnMsg = "OK";
        }
        params.put("return_code", returnCode);
        params.put("return_msg", returnMsg);

        return XmlUtils.map2XmlStr(params);
    }

相关文章

网友评论

      本文标题:微信支付

      本文链接:https://www.haomeiwen.com/subject/jfmyactx.html