微信支付

微信支付代码

代码

package app.front.api;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import com.foxinmy.weixin4j.exception.WeixinException;
import com.foxinmy.weixin4j.http.weixin.XmlResult;
import com.foxinmy.weixin4j.payment.WeixinPayProxy;
import com.foxinmy.weixin4j.payment.mch.MchPayRequest;
import com.foxinmy.weixin4j.payment.mch.Order;
import com.foxinmy.weixin4j.util.Consts;
import com.foxinmy.weixin4j.util.IOUtil;
import com.foxinmy.weixin4j.util.StringUtil;
import com.foxinmy.weixin4j.xml.ListsuffixResultDeserializer;
import com.foxinmy.weixin4j.xml.XmlStream;

import app.base.dao.legouser.OrdersDao;
import app.base.dao.legouser.OrdersItemDao;
import app.base.entity.legouser.Orders;
import app.base.entity.legouser.OrdersItem;
import app.base.entity.legouser.User;
import app.base.service.OrderService;
import app.front.UserContext;
import app.front.api.params.WeixinPayParam;
import component.common.msg.Ret;
import component.common.msg.Rets;
import component.common.utils.LOG;
import component.common.utils.PropertyUtil;
import component.common.utils.RequestUtil;

@Controller
@RequestMapping("api/pay")
public class WeixinPayApi {
    
    private static Map orderIdMap = new HashMap<>();
    
    private String notifyUrl = PropertyUtil.getProperty("pay.notifyUrl");
    @Autowired
    WeixinPayProxy weixinPayProxy;
    @Autowired
    OrdersDao ordersDao;
    @Autowired
    OrdersItemDao ordersItemDao;
    @Autowired
    OrderService orderService;

    @RequestMapping(value = "weixinPay")
    public @ResponseBody Ret pay(HttpServletRequest request,
            HttpServletResponse response
            ,@RequestBody WeixinPayParam param) throws WeixinException, ServletException, IOException {
        User user = UserContext.getLoginUser();
        
        Orders busOrder = ordersDao.get(param.getOrderId());
        
        String openId = user.getOpenId();
        String body = this.buildSetName(busOrder);
        String outTradeNo = UUID.randomUUID().toString().replace("-", "");
        orderIdMap.put(outTradeNo, busOrder.getId());
        double totalFee = busOrder.getPayMoney().doubleValue(); // 订单金额 单位元
        String notifyUrl = this.notifyUrl; // 支付成功回调页面
        String createIp = RequestUtil.getClientIP(request);
        String attach = "";
        // 发起一个JS支付请求,这里有个值得注意的地方:微信返回的预交易ID(payRequest.getPrePayId())是有2小时的时效性的,
        //超过2小时将不能重新发起支付,需重新生成一个`outTradeNo`订单号再次调用createJSPayRequest接口。
        //所以这里的`prePayId`有两种解决方案:
        //1、每次发起支付都重新生成`outTradeNo`订单号,然后调用createJSPayRequest接口。
        //2、把`prePayId`缓存起来,然后通过:MchPayRequest payRequest = new JSAPIPayRequest(prePayId,weixinPayProxy.getPayAccount());
        //构建一个`MchPayRequest`支付对象。两种方式都有利有弊,请根据实际需求而定。
        MchPayRequest payRequest = weixinPayProxy.createJSPayRequest(openId, body, outTradeNo, totalFee, notifyUrl, createIp, attach);
        // 将支付JSON串放到request作用域
        request.setAttribute("jspay", payRequest.toRequestString());
        
        //request.getRequestDispatcher("/pay/pay.jsp").forward(request, response);
        return Rets.successData(payRequest.toRequestObject());
    }
    
    private String buildSetName(Orders busOrder) {
        List orderItems = ordersItemDao.listByProperty("ordersId", busOrder.getId());
        List ret = new ArrayList<>(orderItems.size());
        for(OrdersItem item : orderItems) {
            ret.add(item.getSetName());
        }
        
        return StringUtils.collectionToCommaDelimitedString(ret);
    }
    
    /**
     * 微信支付成功(前端)时的回调通知
     * 
     * @param inputStream
     *            订单回调
     * @return <xml>
* <return_code>SUCCESS/FAIL</return_code>
* <return_msg>如非空,为错误 原因签名失败参数格式校验错误</return_msg>
* </xml> * @throws IOException * @see 支付结果通知 */ @RequestMapping("/weixinNotify") @ResponseBody public String payNotify(HttpServletRequest request) throws IOException { //获取订单信息 String content = StringUtil.newStringUtf8(IOUtil.toByteArray(request.getInputStream())); Order order = ListsuffixResultDeserializer.deserialize(content, Order.class); LOG.info("jsapi_notify_order_info:{}", order); //验证签名 String sign = order.getSign(); String valid_sign = weixinPayProxy.getWeixinSignature().sign(order); LOG.info("微信签名----->sign={},vaild_sign={}", sign, valid_sign); if (!sign.equals(valid_sign)) { return XmlStream.toXML(new XmlResult(Consts.FAIL, "签名错误")); } // TODO 处理业务逻辑,如没有特殊要求可以考虑单独启一个线程去处理自己的业务,对于微信签名过后就可以返回success了。 LOG.info("支付成功:{}",order); String outTradeNo = order.getOutTradeNo(); Long orderId = orderIdMap.get(outTradeNo); orderService.paySuccess(orderId); orderIdMap.remove(outTradeNo); // 需要ajax的形式返回给微信,保证返回值能写到ResponseInputStream就行,Spring mvc使用 @ResponseBody注解,Servlet使用HttpServletResponse#getWrite#write return XmlStream.toXML(new XmlResult(Consts.SUCCESS, "")); } }




订单详情






支付一分钱


你可能感兴趣的:(微信支付)