支付相关-支付宝(微信)

支付宝相关

package com.jg.controller.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradePagePayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.jg.constants.AlipayConfig;
import com.jg.domain.AlipayRefund;
import com.jg.domain.AlipayRequest;
import com.jg.query.AlipayQuery;
import com.jg.util.SerialNumber;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 */
@Controller
@RequestMapping("/alipay")
public class AlipayController {

    private static final Log logger = LogFactory.getLog(AlipayController.class);

    @RequestMapping("/list")
    public String returnPay(HttpServletResponse response)throws Exception{
    /*    response.setCharacterEncoding("utf-8");
        response.setContentType("text/html;charset=" + CHARSET);
        PrintWriter out = response.getWriter();
        out.println("<form name=\"punchout_form\" method=\"post\" action=\"https://openapi.alipay.com/gateway.do?charset=utf-8&method=alipay.trade.page.pay&sign=TDahjscloUt5vpwxRUH0ZwZAikCg37dI1nTst%2BpOoilt4AGFlJKHmLqsVDAViim%2FPkfLNhb%2Bp3faVMw9pF%2FpugTjLsxIeYVBRoWsZCmToJXxSp7YtwaLvVBzybUdvQ3E584AJQGcU8UaRzhCQTFQeQO1Juh6hFNS5mk3sf9g2DJuxWi9ub2Z4h%2BKTx2rD9gt%2FAykKJ0bb%2BgD3B3ymiJo3tWS%2BnWJwTDAvI%2BpPFtgtCRhrrEMxoAEI4PBTwBfNFz08OyTE0iNv%2B1%2FgM2BMIQ1tEPhY74GLdRpuHNN87jiN3HMUxxfALUU7gCa7QfZJGIwtohvkX2sDDKUefdsDGv6Nw%3D%3D&return_url=http%3A%2F%2F127.0.0.1%3A8080%2Falipay%2FreturnUrl&notify_url=http%3A%2F%2F127.0.0.1%3A8080%2Falipay%2FnotifyUrl&version=1.0&app_id=2017101209270409&sign_type=RSA2&timestamp=2018-12-19+17%3A59%3A08&alipay_sdk=alipay-sdk-java-dynamicVersionNo&format=json\">\n" +
                "<input type=\"hidden\" name=\"biz_content\" value=\"{    &quot;out_trade_no&quot;:&quot;DDH20181219175908151&quot;,    &quot;product_code&quot;:&quot;FAST_INSTANT_TRADE_PAY&quot;,    &quot;total_amount&quot;:0.01,    &quot;subject&quot;:&quot;测试测试:0.01&quot;,    &quot;body&quot;:&quot;测试测试:0.01&quot;  }\">\n" +
                "<input type=\"submit\" value=\"立即支付\" style=\"display:none\" >\n" +
                "</form>\n" +
                "<script>document.forms[0].submit();</script>");
        out.close();*/
    return "pay";
    }

    @RequestMapping(value="/pay",method= RequestMethod.POST)
    public void doPay( AlipayRequest aliRequest,ModelMap map, HttpServletRequest httpRequest, HttpServletResponse response) throws ServletException, IOException {
        //获得初始化的AlipayClient
        AlipayClient alipayClient = initAlipayClient();
        //创建API对应的request
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        //在公共参数中设置回跳和通知地址
        alipayRequest.setReturnUrl(AlipayConfig.PAY_URL + AlipayConfig.RETURN_URL);
        alipayRequest.setNotifyUrl(AlipayConfig.PAY_URL + AlipayConfig.NOTIFY_URL);

        response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
        PrintWriter out = response.getWriter();
        if(aliRequest.getTotalAmount()<0.01){
            out.println("充值金额不能小于0.01元");
            out.close();
        }
        //填充业务参数
        // String subject = aliRequest.getSubject();
     /*   alipayRequest.setBizContent("{" +
                "    \"out_trade_no\":\"" + SerialNumber.generaterNextNumber("DDH") + "\"," +
                "    \"product_code\":\"FAST_INSTANT_TRADE_PAY\"," +
                "    \"total_amount\":" + aliRequest.getTotalAmount() + "," +
                "    \"subject\":\"" + subject + "\"," +
                "    \"body\":\"" + aliRequest.getBody() + "\"" +
                "  }");*/
        //第二种封装方式
        //商户订单号,商户网站订单系统中唯一订单号,必填
        String out_trade_no = SerialNumber.generaterNextNumber("DDH");
        // 订单名称,必填
        String subject = "充值金额:"+0.01;
        // 付款金额,必填
        String total_amount="0.01";
        // 商品描述,可空
        String body = "张三充值¥:"+total_amount;
        // 封装请求支付信息
        AlipayTradePagePayModel model=new AlipayTradePagePayModel();
        model.setOutTradeNo(out_trade_no);
        model.setSubject(subject);
        model.setTotalAmount(total_amount);
        model.setBody(body);
        model.setTimeoutExpress("");
        model.setPassbackParams("123");
        // 销售产品码 必填
        model.setProductCode("FAST_INSTANT_TRADE_PAY");
        alipayRequest.setBizModel(model);
        String form = "";
        try {
            form = alipayClient.pageExecute(alipayRequest).getBody(); //调用SDK生成表单
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        out.println(form);
        out.close();
    }

    /**
     * pc端同步通知
     * 不做业务
     * @param
     */
    @RequestMapping(value="/returnUrl")
    public String returnUrl(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws Exception{
        logger.info("------------------------------------pc同步通知-------------------------------------------");
        //获取支付宝GET过来反馈信息
        Map<String,String> params = getParamToMap(request.getParameterMap());

        boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, AlipayConfig.SIGN_TYPE); //调用SDK验证签名

        //——请在这里编写您的程序(以下代码仅作参考)——
        if(signVerified) {
            //商户订单号
            String out_trade_no = params.get("out_trade_no");
            //支付宝交易号
            String trade_no = params.get("trade_no");
            //付款金额
            String total_amount = params.get("total_amount");
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            logger.info("-----------------out_trade_no:"+out_trade_no+"trade_no:"+trade_no+"total_amount:"+total_amount+"---------------------");
            map.put("result", "支付宝支付成功");
        }else {
            response.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
            map.put("result", "支付宝支付失败");
        }
        //——请在这里编写您的程序(以上代码仅作参考)——
        return "alipayResult";
    }

    /**
     * pc端异步通知
     * 做相应的业务处理
     */
    @RequestMapping(value="/notifyUrl",method= RequestMethod.POST)
    public void notifyUrl(ModelMap map, HttpServletRequest request, HttpServletResponse response) throws Exception{
        try {
            logger.info("------------------------------------pc异步通知-------------------------------------------");
            //获取支付宝POST过来反馈信息并转为map
            Map<String,String> params = getParamToMap(request.getParameterMap());
            //logger.info("---------------------------------------------------------------params=========="+params);
            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            //商户订单号
            String out_trade_no = params.get("out_trade_no");
            //支付宝交易号
            String trade_no = params.get("trade_no");
            //交易状态
            String trade_status = params.get("trade_status");

            //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            //计算得出通知验证结果
            //boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
            boolean verify_result = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.CHARSET, "RSA2");
            logger.info("------------------------------------------支付宝异步通知页面验证成功:trade_finished------------------------------verify_result="+verify_result);
            if(verify_result){//验证成功
                //
                //请在这里加上商户的业务逻辑程序代码

                //——请根据您的业务逻辑来编写程序(以下代码仅作参考)——

                if(trade_status.equals("TRADE_FINISHED")){
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                    //如果有做过处理,不执行商户的业务程序
                    logger.info("------------------------------------------支付宝异步通知页面验证成功:trade_finished------------------------------");
                    //注意:
                    //如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
                    //如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
                } else if (trade_status.equals("TRADE_SUCCESS")){
                    //判断该笔订单是否在商户网站中已经做过处理
                    //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                    //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
                    //如果有做过处理,不执行商户的业务程序
                    logger.info("------------------------------------------支付宝异步通知页面验证成功:trade_success------------------------------");
                    //注意:
                    //如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
                }
                //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
                response.getWriter().println("success");
                response.getWriter().close();
                //
            }else{//验证失败
                response.getWriter().println("fail");
                response.getWriter().close();
                logger.info("-------------------------------fail-------------------------------");
            }
        } catch (Exception e) {
            response.getWriter().println("fail");
            response.getWriter().close();
            logger.info("跳转到pc网站支付宝支付-同步不通知-页面-error");
            e.printStackTrace();
        }
    }

    /**
     * 获取对应的参数转为map
     * @param requestParams
     * @return
     */
    private Map<String,String> getParamToMap(Map<String,String[]> requestParams){
        Map<String,String> params = new HashMap<String,String>();
        for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
            String valueStr = "";
            String name = (String) iter.next();
            String[] values = (String[]) requestParams.get(name);
            for (int i = 0; i < values.length; i++) {
                valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
            }
            //乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化。
            //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8");
            params.put(name, valueStr);
        }
        return params;
    }

    /**
     * 支付宝退款,签约的是可退款协议
     * 可使用官方实体类:AlipayTradeRefundModel(setBizModel)
     * @param map
     * @throws Exception
     */
    @RequestMapping(value="/refund",method= RequestMethod.POST)
    public void refund(AlipayRefund refund, ModelMap map) throws Exception{
        //获得初始化的AlipayClient
        AlipayClient alipayClient = initAlipayClient();
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        //标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传
        request.setBizContent("{" +
                "    \"out_trade_no\":\""+refund.getOutTradeNo()+"\"," +
                "    \"trade_no\":\""+refund.getTradeNo()+"\"," +
                "    \"refund_amount\":"+refund.getRefundAmount()+"," +
                "    \"refund_reason\":\""+refund.getRefundReason()+"\"," +
                "    \"out_request_no\":\""+refund.getOutRequestNo()+"\"" +
                "  }");
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            logger.info("-------------------------------调用成功-------------------------------");
        } else {
            logger.info("-------------------------------调用失败-------------------------------");
        }
    }

    /**
     * 支付宝退款查询
     * @param map
     * @throws Exception
     */
    @RequestMapping(value="/refundQuery",method= RequestMethod.POST)
    @ResponseBody
    public AlipayTradeFastpayRefundQueryResponse refundQuery(AlipayRefund refund,ModelMap map) throws Exception{
        //获得初始化的AlipayClient
        AlipayClient alipayClient = initAlipayClient();
        AlipayTradeFastpayRefundQueryRequest request = new AlipayTradeFastpayRefundQueryRequest();
        //out_request_no必填如为空则为out_trade_no
        request.setBizContent("{" +
                "    \"out_trade_no\":\""+refund.getOutTradeNo()+"\"," +
                "    \"trade_no\":\""+refund.getTradeNo()+"\"," +
                "    \"out_request_no\":\""+refund.getOutRequestNo()+"\"" +
                "  }");
        AlipayTradeFastpayRefundQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            logger.info("-------------------------------调用成功-------------------------------");
        } else {
            logger.info("-------------------------------调用失败-------------------------------");
        }
        return response;
    }

    /**
     * 支付宝交易查询
     * @param map
     * @throws Exception
     */
    @RequestMapping("/tradeQuery")
    @ResponseBody
    public AlipayTradeQueryResponse tradeQuery(ModelMap map,AlipayQuery query) throws Exception{
        //获得初始化的AlipayClient
        AlipayClient alipayClient = initAlipayClient();
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
        request.setBizContent("{" +
                "    \"out_trade_no\":\""+query.getOutTradeNo()+"\"," +
                "    \"trade_no\":\""+query.getTradeNo()+"\"" +
                "  }");
        AlipayTradeQueryResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            logger.info("-------------------------------调用成功-------------------------------");
        } else {
            logger.info("-------------------------------调用失败-------------------------------");
        }
        return response;
    }

    /**
     * 支付宝交易关闭
     * @param map
     * @throws Exception
     */
    @RequestMapping("/tradeClose")
    public void tradeClose(ModelMap map) throws Exception{
        //获得初始化的AlipayClient
        AlipayClient alipayClient = initAlipayClient();
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        request.setBizContent("{" +
                "    \"trade_no\":\"2013112611001004680073956707\"," +
                "    \"out_trade_no\":\"HZ0120131127001\"," +
                "    \"operator_id\":\"YX01\"" +
                "  }");
        AlipayTradeCloseResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            System.out.println("调用成功");
        } else {
            System.out.println("调用失败");
        }
    }

    /**
     * 支付宝账单下载
     * 不能下载当天的
     * @param map
     * @throws Exception
     */
    @RequestMapping("/billDownLoad")
    public void billDownLoad(ModelMap map,AlipayQuery query) throws Exception{
        //获得初始化的AlipayClient
        AlipayClient alipayClient = initAlipayClient();
        //先查询账单下载地址
        AlipayDataDataserviceBillDownloadurlQueryRequest request = new AlipayDataDataserviceBillDownloadurlQueryRequest();//创建API对应的request类
        request.setBizContent("{" +
                        "    \"bill_type\":\""+query.getBillType()+"\"," +
                        "    \"bill_date\":\""+query.getBillDate()+"\"" +
                "  }");//设置业务参数
        AlipayDataDataserviceBillDownloadurlQueryResponse response = alipayClient.execute(request);
        String billDownloadUrl = response.getBillDownloadUrl();
        if(billDownloadUrl ==null||billDownloadUrl.length()==0){
            return;
        }
        //根据response中的结果继续业务逻辑处理
        //将接口返回的对账单下载地址传入urlStr
        String urlStr = billDownloadUrl;
        logger.info("-------------------------------urlStr-------------------------------:::"+urlStr);
        //指定希望保存的文件路径
        String filePath = "/bill/20181218.csv.zip";
        URL url = null;
        HttpURLConnection httpUrlConnection = null;
        InputStream fis = null;
        FileOutputStream fos = null;
        try {
            url = new URL(urlStr);
            httpUrlConnection = (HttpURLConnection) url.openConnection();
            httpUrlConnection.setConnectTimeout(5 * 1000);
            httpUrlConnection.setDoInput(true);
            httpUrlConnection.setDoOutput(true);
            httpUrlConnection.setUseCaches(false);
            httpUrlConnection.setRequestMethod("GET");
            httpUrlConnection.setRequestProperty("Charsert", "UTF-8");
            httpUrlConnection.connect();
            fis = httpUrlConnection.getInputStream();
            byte[] temp = new byte[1024];
            int b;
            fos = new FileOutputStream(new File(filePath));
            while ((b = fis.read(temp)) != -1) {
                fos.write(temp, 0, b);
                fos.flush();
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (fis != null) fis.close();
                if (fos != null) fos.close();
                if (httpUrlConnection != null) httpUrlConnection.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 初始化AlipayClient
     * @return
     */
    private AlipayClient initAlipayClient(){
        AlipayClient alipayClient = new DefaultAlipayClient(
                AlipayConfig.GATEWAY_URL,
                AlipayConfig.APP_ID,
                AlipayConfig.APP_PRIVATE_KEY,
                AlipayConfig.FORMAT,
                AlipayConfig.CHARSET,
                AlipayConfig.ALIPAY_PUBLIC_KEY,
                AlipayConfig.SIGN_TYPE);
        return alipayClient;
    }

    /**
     * 支付宝app支付未测试
     * 可使用官方实体:AlipayTradeAppPayModel(setBizModel)
     * @param httpRequest
     * @param response
     * @throws Exception
     */
    @RequestMapping("/app")
    public void appPay(HttpServletRequest httpRequest, HttpServletResponse httpResponse)throws Exception{
        AlipayClient alipayClient = initAlipayClient();
        AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
        request.setBizContent("{" +
                "\"timeout_express\":\"90m\"," +
                "\"total_amount\":\"0.01\"," +
                "\"seller_id\":\""+AlipayConfig.APP_ID+"\"," +
                "\"product_code\":\"QUICK_MSECURITY_PAY\"," +
                "\"body\":\"测试\"," +
                "\"subject\":\"测试\"," +
                "\"out_trade_no\":\""+SerialNumber.generaterNextNumber("DDH")+"\"," +
                "\"time_expire\":\"2018-12-21 11:40\"," +
                "\"goods_type\":\"0\"" +
                "  }");
        request.setReturnUrl(AlipayConfig.PAY_URL + AlipayConfig.RETURN_URL);
        request.setNotifyUrl(AlipayConfig.PAY_URL + AlipayConfig.NOTIFY_URL);
        AlipayTradeAppPayResponse response = alipayClient.pageExecute(request);
        if(response.isSuccess()){
            logger.info("-------------------------------调用成功-------------------------------");
        } else {
            logger.info("-------------------------------调用失败-------------------------------");
        }
        httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
        PrintWriter out = httpResponse.getWriter();
        out.println(response.getBody());
        out.close();
    }

    /**
     * 手机网站支付接口2.0
     * @throws AlipayApiException
     */
    @RequestMapping("/mobileWeb")
    public  void alipayMobileWeb(HttpServletRequest httpRequest, HttpServletResponse httpResponse)throws Exception{
        AlipayClient alipayClient = initAlipayClient();
        AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
        request.setBizContent("{" +
                "\"body\":\"测试测试。\"," +
                "\"subject\":\"测试测试\"," +
                "\"out_trade_no\":\"70501111111S00111129\"," +
                "\"timeout_express\":\"90m\"," +
                "\"time_expire\":\"2018-12-21 11:40\"," +
                "\"total_amount\":0.01," +
                "\"seller_id\":\""+AlipayConfig.APP_ID+"\"," +
                "\"goods_type\":\"0\"," +
                "\"quit_url\":\""+"http://localhost:8080/alipay/list"+"\"," +
                "\"product_code\":\"QUICK_WAP_WAY\"" +
                "  }");
        request.setReturnUrl(AlipayConfig.PAY_URL + AlipayConfig.RETURN_URL);
        request.setNotifyUrl(AlipayConfig.PAY_URL + AlipayConfig.NOTIFY_URL);
        AlipayTradeWapPayResponse response = alipayClient.pageExecute(request);
        if(response.isSuccess()){
            logger.info("-------------------------------调用成功-------------------------------");
        } else {
            logger.info("-------------------------------调用失败-------------------------------");
        }
        httpResponse.setContentType("text/html;charset=" + AlipayConfig.CHARSET);
        PrintWriter out = httpResponse.getWriter();
        out.println(response.getBody());
        out.close();
    }
}

微信:

package com.jg.controller.wechatpay;

import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.jg.constants.WeChatPayConfig;
import com.jg.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import static com.jg.constants.AlipayConfig.PAY_URL;

/**
 */
@Controller
@RequestMapping("/wx")
public class WxPayController {
    private static final Log logger = LogFactory.getLog(WxPayController.class);

    @RequestMapping("/wxPayH5")
    @ResponseBody
    public Result<String> wxPayH5(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
        Result<String> result = Result.isFail();
        String url = "";
        // 付款金额,必填
        String total_fee = request.getParameter("total_fee");
        // ip地址获取
        String basePath = request.getServerName() + ":" + request.getServerPort();
        //初始化请求参数
        SortedMap<String, Object> packageParams = initMapParamsOfH5(total_fee);
        try {
            //生成签名
            String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
            packageParams.put("sign", sign);
            //转为xml格式
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            //统一下单
            String resXml = HttpUtil.postData(WeChatPayConfig.UNIFIED_ORDER_URL, requestXML);
            //返回xml解析为map
            Map map = PayCommonUtil.doXMLParse(resXml);
            String return_code = (String) map.get("return_code");
            String return_msg = (String) map.get("return_msg");
            String result_code = (String) map.get("result_code");
            if ("SUCCESS".equals(return_code) && "OK".equals(return_msg) && "SUCCESS".equals(result_code)) {
                url = (String) map.get("mweb_url");//调微信支付接口地址
                if (!StringUtils.isEmpty(url)) {
                    //确认支付过后跳的地址,需要经过urlencode处理
                    //String urlString = URLEncoder.encode("http://localhost:8080/alipay/list", "UTF-8");
                    //String mweb_url = url+"&redirect_url="+urlString;
                    result.setStatus(0);
                    result.setData(url);
                    return result;
                } else {
                    result.setMsg("统一支付接口获取预支付订单出错:" + return_msg);
                    return result;
                }
            } else {
                result.setMsg("支付错误:" + return_msg);
                return result;
            }
        } catch (Exception e) {
            result.setMsg("支付错误");
            return result;
        }
    }

    /**
     * 执行回调 确认支付后处理事件 例如添加金额到数据库等操作
     *
     * @param request
     * @param response
     * @throws Exception
     */
    @RequestMapping("/notify")
    public void weixin_notify(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
        logger.info("进入支付h5回调=====================");
        String xmlMsg = readData(request);
        logger.info("pay notice---------" + xmlMsg);
        Map params = PayCommonUtil.doXMLParse(xmlMsg);
//		String appid  = params.get("appid");
//		//商户号
//		String mch_id  = params.get("mch_id");
        String result_code = params.get("result_code") + "";
//		String openId      = params.get("openid");
//		//交易类型
//		String trade_type      = params.get("trade_type");
//		//付款银行
//		String bank_type      = params.get("bank_type");
//		// 总金额
//		String total_fee     = params.get("total_fee");
//		//现金支付金额
//		String cash_fee     = params.get("cash_fee");
//		// 微信支付订单号
//		String transaction_id      = params.get("transaction_id");
//		// 商户订单号
//		String out_trade_no      = params.get("out_trade_no");
//		// 支付完成时间,格式为yyyyMMddHHmmss
//		String time_end      = params.get("time_end");

        /以下是附加参数///

        String attach = params.get("attach") + "";
//		String fee_type      = params.get("fee_type");
//		String is_subscribe      = params.get("is_subscribe");
//		String err_code      = params.get("err_code");
//		String err_code_des      = params.get("err_code_des");
        // 过滤空 设置 TreeMap
     /*   SortedMap<String, String> packageParams = new TreeMap<String, String>();
        Iterator it = params.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = params.get(parameter) + "";
            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            logger.info("value===============" + v);
            packageParams.put(parameter, v);
        }*/

        //判断签名是否正确
        if(PayCommonUtil.isTenpaySign(params,WeChatPayConfig.API_KEY)) {
            //------------------------------
            //处理业务开始
            //------------------------------
            String resXml = "";
            if("SUCCESS".equals(params.get("result_code"))){
                // 这里是支付成功
                //执行自己的业务逻辑
                String mch_id = (String)params.get("mch_id");
                String openid = (String)params.get("openid");
                String is_subscribe = (String)params.get("is_subscribe");
                String out_trade_no = (String)params.get("out_trade_no");

                String total_fee = (String)params.get("total_fee");

                System.out.println("mch_id:"+mch_id);
                System.out.println("openid:"+openid);
                logger.info("is_subscribe:"+is_subscribe);
                logger.info("out_trade_no:"+out_trade_no);
                logger.info("total_fee:"+total_fee);

                //执行自己的业务逻辑

                logger.info("支付成功============支付金额:" + total_fee);
                //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";

            } else {
                logger.info("支付失败,错误信息:" + params.get("err_code"));
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            }
            //------------------------------
            //处理业务完毕
            //------------------------------
            BufferedOutputStream out = null;
            try {
                out = new BufferedOutputStream(response.getOutputStream());
                out.write(resXml.getBytes());
                out.flush();
            } catch (Exception e) {
                e.printStackTrace();
                logger.info("关闭流失败:"+e.getMessage());
            } finally {
                if (out != null) {
                    out.close();
                }
            }
        } else{
            logger.info("通知签名验证失败");
        }

    }

    /**
     * 用户扫二维码付
     *
     * @param request
     * @param response
     * @param model
     * @return
     * @throws Exception
     */
    @RequestMapping("/scanQRCode")
    @ResponseBody
    public Result<String> scanQRCode(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
        Result<String> result = Result.isFail();
        String url = "";
        // 付款金额,必填
        String total_fee = request.getParameter("total_fee");
        // ip地址获取
        String basePath = request.getServerName() + ":" + request.getServerPort();
        //初始化请求参数
        SortedMap<String, Object> packageParams = initMapParams(total_fee);
        // 回调接口
        String notify_url = PAY_URL + WeChatPayConfig.NOTIFY_URL;
        packageParams.put("notify_url", notify_url);
        //JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,H5支付的交易类型为MWEB
        packageParams.put("trade_type", "NATIVE");
        try {
            //生成签名
            String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
            packageParams.put("sign", sign);
            //转为xml格式
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            //统一下单
            String resXml = HttpUtil.postData(WeChatPayConfig.UNIFIED_ORDER_URL, requestXML);
            //返回xml解析为map
            Map map = PayCommonUtil.doXMLParse(resXml);
            String return_code = (String) map.get("return_code");
            String return_msg = (String) map.get("return_msg");
            String result_code = (String) map.get("result_code");
            if ("SUCCESS".equals(return_code) && "OK".equals(return_msg) && "SUCCESS".equals(result_code)) {
                //mweb_url为拉起微信支付收银台的中间页面,可通过访问该url来拉起微信客户端,完成支付,mweb_url的有效期为5分钟。
                url = (String) map.get("code_url");//用来生成二维码
                ByteArrayOutputStream out = new ByteArrayOutputStream();
                //将返回预支付交易链接(code_url)生成二维码图片
                //这里使用的是zxing   <span style="color:#ff0000;"><strong>说明1(见文末)</strong></span>
                try {
                    int width = 200;
                    int height = 200;
                    Hashtable hints = new Hashtable();
                    hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
                    hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M);
                    hints.put(EncodeHintType.MARGIN, 2);
                    BitMatrix bitMatrix = new MultiFormatWriter().encode(url, BarcodeFormat.QR_CODE, width, height, hints);
                    BufferedImage image = MatrixToImageWriter.toBufferedImage(bitMatrix);
                    ImageIO.write(image, "png", out);
                    /**
                     * 原生转码前面没有 data:image/png;base64 这些字段,返回给前端是无法被解析,可以让前端加,也可以在下面加上
                     * import com.sun.org.apache.xml.internal.security.utils.Base64;
                     * import sun.misc.BASE64Encoder;
                     * 但还是java8的速度快
                     */
                    url = new String("data:image/png;base64," + Base64.getEncoder().encodeToString(out.toByteArray()));
                } catch (Exception e) {
                } finally {
                    if (out != null) {
                        try {
                            out.flush();
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }
                if (!StringUtils.isEmpty(url)) {
                    result.setStatus(0);
                    result.setData(url);
                    return result;
                } else {
                    result.setMsg("统一支付接口获取预支付订单出错:" + return_msg);
                    return result;
                }
            } else {
                result.setMsg("支付错误:" + return_msg);
                return result;
            }
        } catch (Exception e) {
            result.setMsg("支付错误");
            return result;
        }
    }

    public static String readData(HttpServletRequest request) {
        BufferedReader br = null;
        try {
            StringBuilder result = new StringBuilder();
            br = request.getReader();
            for (String line; (line = br.readLine()) != null; ) {
                if (result.length() > 0) {
                    result.append("\n");
                }
                result.append(line);
            }

            return result.toString();
        } catch (IOException e) {
            throw new RuntimeException(e);
        } finally {
            if (br != null)
                try {
                    br.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }

    /**
     * 付款码支付
     *
     *收银员使用扫码设备读取微信用户付款码以后,二维码或条码信息会传送至商户收银台,由商户收银台或者商户后台调用该接口发起支付。
     *提醒1:提交支付请求后微信会同步返回支付结果。当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】,查询支付实际交易结果;当返回结果为“USERPAYING”时,商户系统可设置间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒);
     *提醒2:在调用查询接口返回后,如果交易状况不明晰,请调用【撤销订单API】,此时如果交易失败则关闭订单,该单不能再支付成功;如果交易成功,则将扣款退回到用户账户。当撤销无返回或错误时,请再次调用。注意:请勿扣款后立即调用【撤销订单API】,建议至少15秒后再调用。撤销订单API需要双向证书。
     * @param request
     * @param response
     * @param model
     * @return
     * @throws Exception
     */
    @RequestMapping("/paymentCode")
    @ResponseBody
    public Result<String> paymentCode(HttpServletRequest request, HttpServletResponse response, ModelMap model) throws Exception {
        Result<String> result = Result.isFail();
        String url = "";
        // 付款金额,必填
        String total_fee = request.getParameter("total_fee");
        //用户的付款码
        String auth_code = request.getParameter("auth_code");
        // ip地址获取
        String basePath = request.getServerName() + ":" + request.getServerPort();
        //初始化请求参数
        SortedMap<String, Object> packageParams = initMapParams(total_fee);
        //JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,H5支付的交易类型为MWEB,付款码支付不需要
        packageParams.put("auth_code", auth_code);

        try {
            //生成签名
            String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
            packageParams.put("sign", sign);
            //转为xml格式
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            //付款码支付
            String resXml = HttpUtil.postData(WeChatPayConfig.PAYMENT_CODE_URL, requestXML);
            //返回xml解析为map
            Map map = PayCommonUtil.doXMLParse(resXml);
            //通信标识
            String return_code = (String) map.get("return_code");
            String err_code = (String) map.get("err_code");
            if ("SUCCESS".equals(return_code)) {
                String result_code = (String) map.get("result_code");
                if ("SUCCESS".equals(result_code)) {
                    //openid用户在商户appid 下的唯一标识
                    url = (String) map.get("openid") + "----支付金额:" + (String) map.get("total_fee")+"分";
                    if (!StringUtils.isEmpty(url)) {
                        result.setStatus(0);
                        result.setData(url);
                        return result;
                    }
                }else if("SYSTEMERROR".equals(err_code)){
                    //如果当前交易返回的支付状态是明确的错误原因造成的支付失败(支付确认失败),请重新下单支付;
                    // 如果当前交易返回的支付状态是不明错误(支付结果未知),请调用查询订单接口确认状态,如果长时间(建议30秒)都得不到明确状态请调用撤销订单接口。
                    //当返回结果为“系统错误”时,商户系统等待5秒后调用【查询订单API】
                    TimeUnit.SECONDS.sleep(5);
                    String queryXml = HttpUtil.postData(WeChatPayConfig.CHECK_ORDER_URL, requestXML);
                    //返回xml解析为map
                    Map queryMap = PayCommonUtil.doXMLParse(queryXml);
                    //交易状态,SUCCESS—支付成功
                    //REFUND—转入退款 NOTPAY—未支付 CLOSED—已关闭 REVOKED—已撤销(付款码支付)USERPAYING--用户支付中(付款码支付)PAYERROR--支付失败(其他原因,如银行返回失败)
                    String trade_state = (String) queryMap.get("trade_state");
                    result_code = (String) queryMap.get("result_code");
                    if("SUCCESS".equals(trade_state)&&"SUCCESS".equals(result_code)){
                        url = (String) map.get("total_fee");
                        result.setStatus(0);
                        result.setData(url);
                        return result;
                    }else if("USERPAYING".equals(trade_state)){
                        //间隔时间(建议10秒)重新查询支付结果,直到支付成功或超时(建议30秒)
                        int i =0;
                        while(true){
                            TimeUnit.SECONDS.sleep(10);
                            String queryPayxml = HttpUtil.postData(WeChatPayConfig.CHECK_ORDER_URL, requestXML);
                            //返回xml解析为map
                            Map queryPayMap = PayCommonUtil.doXMLParse(queryPayxml);
                            trade_state = (String) queryPayMap.get("trade_state");
                            if("SUCCESS".equals(trade_state)){
                                url = (String) map.get("total_fee");
                                result.setStatus(0);
                                result.setData(url);
                                return result;
                            }else{
                                i++;
                            }
                            //已超过30秒等待
                            if(i==2){
                                String err_code_des = (String) queryPayMap.get("err_code_des");
                                //订单撤销
                                String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
                                result.setMsg(err_code_des);
                                return result;
                            }
                        }
                    }
                    //ORDERPAID
                    //撤销订单,调用支付接口后请勿立即调用撤销订单API,建议支付后至少15s后再调用撤销订单接口
                    String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
                    //返回错误原因
                    result.setMsg("付款码支付错误"+queryMap.get("err_code_des"));
                    return result;
                }
                //撤销订单
                String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
                //返回错误原因
                result.setMsg("付款码支付错误"+map.get("err_code_des"));
                return result;
            } else {
                //撤销订单
                String cancelPayxml = HttpUtil.postData(WeChatPayConfig.CANCEL_URL, requestXML);
                result.setMsg("付款码支付错误"+map.get("err_code_des"));
                return result;
            }
        } catch (Exception e) {
            result.setMsg("付款码支付错误");
            return result;
        }
    }

    /**
     * 订单查询
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @RequestMapping("/query")
    @ResponseBody
    public Result<String> queryOrder(HttpServletRequest request, HttpServletResponse response) throws Exception {
        Result<String> result = Result.isFail();
        //商户订单号或微信订单号(transaction_id)二选一
        String out_trade_no = request.getParameter("out_trade_no");
        //随机字符串
        String nonce_str = request.getParameter("nonce_str");
        //初始化请求参数
        SortedMap<String, Object> packageParams = initMapQueryParams(out_trade_no,nonce_str);
        try {
            //生成签名
            String sign = PayCommonUtil.createSign("UTF-8", packageParams, WeChatPayConfig.API_KEY);
            packageParams.put("sign", sign);
            //转为xml格式
            String requestXML = PayCommonUtil.getRequestXml(packageParams);
            //付款码支付
            String resXml = HttpUtil.postData(WeChatPayConfig.CHECK_ORDER_URL, requestXML);
            //返回xml解析为map
            Map map = PayCommonUtil.doXMLParse(resXml);
            String return_code = (String) map.get("return_code");
            String return_msg = (String) map.get("return_msg");
            result.setData(map.toString());
            result.setStatus(0);
            return result;
        }catch (Exception e){

        }
        return result;
    }
        /**
         * 账号信息初始化
         * 可用实体类来封装,本测试未使用
         */
    private void initClient() {
        // 账号信息
        String appid = WeChatPayConfig.APP_ID; // appid
        String mch_id = WeChatPayConfig.MCH_ID; // 商业号
        String key = WeChatPayConfig.API_KEY; // key
    }

    /**
     * 初始化公共参数
     *
     * @param total_fee
     * @return
     */
    private SortedMap<String, Object> initMapParams(String total_fee) {

        String currTime = PayCommonUtil.getCurrTime();
        String strTime = currTime.substring(8, currTime.length());
        String strRandom = PayCommonUtil.buildRandom(4) + "";
        String nonce_str = strTime + strRandom;
        // 价格 注意:价格的单位是分
        String order_price = new BigDecimal(total_fee).multiply(new BigDecimal(100)).toString().split("\\.")[0];
        // 自己网站上的订单号
        String out_trade_no = SerialNumber.generaterNextNumber("DDH");
        // 获取发起电脑 ip
        String spbill_create_ip = "127.0.0.1";

        // 设置package订单参数
        SortedMap<String, Object> packageParams = new TreeMap<String, Object>();
        packageParams.put("appid", WeChatPayConfig.APP_ID);
        packageParams.put("body", "测试测试");
        packageParams.put("mch_id", WeChatPayConfig.MCH_ID);
        // 生成签名的时候需要你自己设置随机字符串
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("out_trade_no", out_trade_no);
        packageParams.put("spbill_create_ip", spbill_create_ip);
        packageParams.put("total_fee", order_price);
        return packageParams;
    }

    /**
     * 初始化H5参数
     *
     * @param total_fee
     * @return
     */
    private SortedMap<String, Object> initMapParamsOfH5(String total_fee) {
        SortedMap<String, Object> packageParams = initMapParams(total_fee);
        // 回调接口
        String notify_url = PAY_URL + WeChatPayConfig.NOTIFY_URL;
        packageParams.put("notify_url", notify_url);
        //扫码支付参数
        packageParams.put("scene_info", "{\"h5_info\": {\"type\":\"Wap\",\"wap_url\": \"http://localhost:8080\",\"wap_name\": \"测试测试\"}}");
        //JSAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,H5支付的交易类型为MWEB
        packageParams.put("trade_type", "MWEB");
        return packageParams;
    }

    /**
     * 初始化查询参数
     *
     * @param total_fee
     * @return
     */
    private SortedMap<String, Object> initMapQueryParams(String out_trade_no,String nonce_str) {
        // 设置package订单参数
        SortedMap<String, Object> packageParams = new TreeMap<String, Object>();
        packageParams.put("appid", WeChatPayConfig.APP_ID);
        packageParams.put("mch_id", WeChatPayConfig.MCH_ID);
        // 生成签名的时候需要你自己设置随机字符串
        packageParams.put("nonce_str", nonce_str);
        packageParams.put("out_trade_no", out_trade_no);
        return packageParams;
    }
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值