java后端配合app前端的支付宝和微信支付(逻辑相关代码)

package com.lanecard.shop.data.api.v2.trade;

import java.io.File;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

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

import org.apache.log4j.Logger;
import org.jdom.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

import com.ibm.icu.text.SimpleDateFormat;
import com.lanecard.common.PayOnlineConstants;
import com.lanecard.dao.entity.trade.TradeOrder;
import com.lanecard.dao.entity.trade.TradeOrderPayment;
import com.lanecard.dao.vo.TradeOrderPayStatus;
import com.lanecard.dao.vo.TradeOrderPayType;
import com.lanecard.dao.vo.TradeOrderWXPayStatus;
import com.lanecard.exception.AppException;
import com.lanecard.shop.data.api.error.ErrorUtil;
import com.lanecard.shop.data.api.error.Errors;
import com.lanecard.shop.data.api.v2.BaseApi;
import com.lanecard.shop.service.trade.TradeOrderPaymentService;
import com.lanecard.shop.service.trade.TradeOrderService;
import com.lanecard.taglib.util.BrowserUtils;
import com.lanecard.util.alipay.AlipayCore;
import com.lanecard.util.alipay.AlipayPayNotify;
import com.lanecard.util.alipay.AlipayRefundNotify;
import com.lanecard.util.alipay.AlipaySubmit;
import com.lanecard.util.alipay.RSA;
import com.lanecard.util.tenpay.TenpayHttpClientUtil;
import com.lanecard.util.tenpay.WXUtil;
import com.lanecard.util.tenpay.XMLUtil;

@Controller
@RequestMapping(BaseApi.URI_PREFIX_V2 + “/playOnline”)
public class PayOnlineApi extends BaseApi {
static final Logger log = Logger.getLogger(PayOnlineApi.class);

@Autowired
private TradeOrderService tradeOrderservice;
@Autowired
private TradeOrderPaymentService tradeOrderPaymentService;

//**************************************微信支付*****************************************
/*
 微信在线支付 生成 预支付ID
    除被扫支付场景以外,商户系统先调用该接口在微信支付服务后台生成预支付交易单,返回正确的预支付交易回话标识后再按扫码、JSAPI、APP等
 * 有用非必传参数 设备号:device_info 》 APP 
 * 商品详情:detail 》 商品名称明细列表 
 * 附加数据:attach 自定义信息 
 * 交易起始时间:time_start 》 20091225091010
 * 交易结束时间:time_expire 》 20091227091010 最短失效时间间隔必须大于5分钟
 * 商品标记:goods_tag 商品标记,代金券或立减优惠功能的参数
 */
@RequestMapping("/tenpay/prepaid")
public ModelAndView tenpayPrepaid(String orderId,HttpServletRequest request) throws AppException, IOException{      
    ModelAndView model = new ModelAndView();

    //通过订单号获取订单信息
    TradeOrder tradeOrder = tradeOrderservice.getById(orderId);

    if(tradeOrder!=null){
        boolean b = true;

        //首先检查此订单是否支付过和支付状态
        TradeOrderPayment checktopay= tradeOrderPaymentService.selectByOrderId(orderId);

        if(checktopay!=null){//此订单调用过支付 调用查询接口查看支付状态
            //调用查询方法
            Map<String,String> map = wzQuery(orderId);
            String resultCode = map.get("resultCode");

            if("ERROR".equals(resultCode)){//订单查询失败
                b = false;
                String message = map.get("message");
                ErrorUtil.fill(model, Errors.ERR_GLOBAL_500, message);
            }else{
                String tradeState = map.get("tradeState");//获取订单在微信端状态

                //支付成功或者退款中 说明逻辑错误
                if(TradeOrderWXPayStatus.SUCCESS.name().equals("tradeState") || TradeOrderWXPayStatus.REFUND.name().equals("tradeState")){
                    b = false;
                    ErrorUtil.fill(model, Errors.ERR_GLOBAL_500, "订单已支付成功或者退款中");
                }else{//还有4种情况 需要调用关单接口
                    //调用关单方法
                    map = wzClose(orderId);
                    resultCode = map.get("resultCode");

                    if("ERROR".equals(resultCode)){//订单关单失败
                        b = false;
                        String message = map.get("message");
                        ErrorUtil.fill(model, Errors.ERR_GLOBAL_500, message);
                    }else{
                        //关单成功 修改支付表支付状态
                        TradeOrderPayment tradeOrderPayment = new TradeOrderPayment();

                        tradeOrderPayment.setOrderId(orderId);
                        tradeOrderPayment.setStatus(TradeOrderPayStatus.C.name());

                        tradeOrderPaymentService.save(tradeOrderPayment);
                    }
                }
            }

        }

        if(b){
            //在在线支付表trade_order_payment 生成支付记录
            insertTradeOrderPayment(TradeOrderPayType.W.name(),tradeOrder);

            //调用生成预支付id方法
            Map<String,String> map = createPrepayId(tradeOrder, request);
            String resultCode = map.get("resultCode");

            if("ERROR".equals(resultCode)){//生成预支付订单失败
                String message = map.get("message");
                ErrorUtil.fill(model, Errors.ERR_GLOBAL_500, message);
            }else{
                String prepayId = map.get("prepayId");
                //为app准备 支付参数
                attr(model, "data", prepareParmaForApp(prepayId));
            }
        }
    }else{
        log.warn("【生成预支付id失败,订单不存在,订单号="+orderId+"】");
        ErrorUtil.fill(model, Errors.ERR_ORDER_NOT_EXIST);
    }

    return model;
}

/*
 微信查询订单
    该接口提供所有微信支付订单的查询,商户可以通过该接口主动查询订单状态,完成下一步的业务逻辑。
    需要调用查询接口的情况:
    ◆ 当商户后台、网络、服务器等出现异常,商户系统最终未接收到支付通知;
    ◆ 调用支付接口后,返回系统错误或未知交易状态情况;
    ◆ 调用关单或撤销接口API之前,需确认支付状态;
*/
@RequestMapping("/tenpay/query")
public ModelAndView tenpayQuery(String orderId) throws AppException, IOException{
    ModelAndView model = new ModelAndView();    

    //调用查询方法
    Map<String,String> map = wzQuery(orderId);
    String resultCode = map.get("resultCode");

    if("ERROR".equals(resultCode)){//查询失败
        String message = map.get("message");
        ErrorUtil.fill(model, Errors.ERR_GLOBAL_500, message);
    }else{
        String payStatus = map.get("payStatus");
        String tradeState = map.get("tradeState");
        attr(model, "payStatus", payStatus);
        attr(model, "tradeState", tradeState);
    }

    return model;
}

/*
  微信订单申请退款
    当交易发生之后一段时间内,由于买家或者卖家的原因需要退款时,卖家可以通过退款接口将支付款退还给买家,
    微信支付将在收到退款请求并且验证成功之后,按照退款规则将支付款按原路退到买家帐号上。
    注意:
    1、交易时间超过一年的订单无法提交退款;
    2、微信支付退款支持单笔交易分多次退款,多次退款需要提交原支付订单的商户订单号和设置不同的退款单号。一笔退款失败后重新提交,
    要采用原来的退款单号。总退款金额不能超过用户实际支付金额。

@RequestMapping("/tenpay/refund")
public void tenpayRefund(HttpServletRequest request,HttpServletResponse response) throws AppException, IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException{   
    //set参数
    Map<String,String> paramsMap = new TreeMap<String,String>();
    paramsMap.put("appid", PayOnlineConstants.APP_ID);
    paramsMap.put("mch_id", PayOnlineConstants.MCH_ID);
    paramsMap.put("nonce_str", WXUtil.getNonceStr());
    paramsMap.put("op_user_id", PayOnlineConstants.MCH_ID); 
    paramsMap.put("out_refund_no", WXUtil.getNonceStr());
    paramsMap.put("out_trade_no", "1752405167");//微信订单号 , 商户订单号 二选一
    paramsMap.put("refund_fee", "1"); 
    paramsMap.put("total_fee", "1"); 
    paramsMap.put("sign", WXUtil.getSign(paramsMap));

    //获取证书路径
    String ca_url = this.getClass().getClassLoader().getResource("ca.cer").toString();
    String p12_url = this.getClass().getClassLoader().getResource("shop_apiclient_cert.p12").toString();
    if(ca_url.startsWith("file")) {//window下面获取url有file:/D:... linux下直接是D:..
        ca_url=ca_url.substring(6, ca_url.length());
    }
    if(p12_url.startsWith("file")) {
        p12_url=p12_url.substring(6, p12_url.length());
    }

    TenpayHttpClientUtil httpClient = new TenpayHttpClientUtil();
    //设置证书 双向https
    httpClient.setCaInfo(new File(ca_url));
    httpClient.setCertInfo(new File(p12_url), "1300877301");//财付通账号
    httpClient.setMethod("POST");
    httpClient.setReqContent(PayOnlineConstants.ORDER_REFUND+"?"+WXUtil.getParams(paramsMap));

    httpClient.callHttps();
    String resContent = httpClient.getResContent();
    try {
        response.getWriter().println(XMLUtil.doXMLParse(resContent));
        response.getWriter().flush();
        response.getWriter().close();

        log.info("【申请退款】"+XMLUtil.doXMLParse(resContent));
    } catch (JDOMException e) {
        e.printStackTrace();
    }
}



  微信订单退款查询
    提交退款申请后,通过调用该接口查询退款状态。退款有一定延时,用零钱支付的退款20分钟内到账,银行卡支付的退款3个工作日后重新查询退款状态。

@RequestMapping("/tenpay/refundQuery")
public void tenpayRefundQuery(HttpServletRequest request,HttpServletResponse response) throws AppException, IOException{
    //set参数
    Map<String,String> paramsMap = new TreeMap<String,String>();
    paramsMap.put("appid", PayOnlineConstants.APP_ID);
    paramsMap.put("mch_id", PayOnlineConstants.MCH_ID);
    paramsMap.put("nonce_str", WXUtil.getNonceStr());
    paramsMap.put("out_trade_no", "1752405167");//微信订单号 , 商户订单号,商户退款单号 和 微信退款单号 四选一  
    paramsMap.put("sign", WXUtil.getSign(paramsMap));

    TenpayHttpClientUtil httpClient = new TenpayHttpClientUtil();
    if (httpClient.callHttpPost(PayOnlineConstants.ORDER_REFUND_QUERY, WXUtil.getParams(paramsMap))) {
        String resContent = httpClient.getResContent();
        try {
            response.getWriter().println(XMLUtil.doXMLParse(resContent));
            response.getWriter().flush();
            response.getWriter().close();

            log.info("【订单退款查询】"+XMLUtil.doXMLParse(resContent));
        } catch (JDOMException e) {
            e.printStackTrace();
        }
    }
}



  微信订单下载对账单
    商户可以通过该接口下载历史交易清单。比如掉单、系统错误等导致商户侧和微信侧数据不一致,通过对账单核对后可校正支付状态。
    注意:
    1、微信侧未成功下单的交易不会出现在对账单中。支付成功后撤销的交易会出现在对账单中,跟原支付单订单号一致,bill_type为REVOKED;
    2、微信在次日9点启动生成前一天的对账单,建议商户10点后再获取;
    3、对账单中涉及金额的字段单位为“元”。

@RequestMapping("/tenpay/downloadbill")
public void tenpayDownloadbill(HttpServletRequest request,HttpServletResponse response) throws AppException, IOException{
    //set参数
    Map<String,String> paramsMap = new TreeMap<String,String>();
    paramsMap.put("appid", PayOnlineConstants.APP_ID);
    paramsMap.put("mch_id", PayOnlineConstants.MCH_ID);
    paramsMap.put("nonce_str", WXUtil.getNonceStr());
    paramsMap.put("bill_date", "20151222");//下载对账单的日期,格式:20140603
    paramsMap.put("bill_type", "ALL");//ALL,返回当日所有订单信息,默认值  SUCCESS,返回当日成功支付的订单 REFUND,返回当日退款订单  REVOKED,已撤销的订单
    paramsMap.put("sign", WXUtil.getSign(paramsMap));

    TenpayHttpClientUtil httpClient = new TenpayHttpClientUtil();
    if (httpClient.callHttpPost(PayOnlineConstants.ORDER_DOWNLOAD_BILL, WXUtil.getParams(paramsMap))) {
        String resContent = httpClient.getResContent();
        try {
            response.getWriter().println(XMLUtil.doXMLParse(resContent));
            response.getWriter().flush();
            response.getWriter().close();

            log.info("【下载对账单】"+XMLUtil.doXMLParse(resContent));
        } catch (JDOMException e) {
            e.printStackTrace();
        }
    }
}*/



//********************************支付宝支付*****************************************


/*
 支付宝 即时到账交易 
*/
@RequestMapping("/alipay/prepareParams")
public void alipayPrepareParams(HttpServletRequest request,HttpServletResponse response) throws Exception{
    String payment_type = "1";//支付类型 不能修改
    String notify_url = PayOnlineConstants.ALI_PAY_NOTIFY_URL;//异步通知服务器地址
    String out_trade_no = "1123233213";//商户订单号 
    String subject = "测试支付宝即时到账";//订单名称 
    String total_fee = "0.01";//付款金额  单位为RMB-Yuan。取值范围为[0.01,100000000.00],精确到小数点后两位
    String body = "下单试试";//订单描述 如果是多种商品,请将商品描述字符串累加传给body
    String appenv = "system=android^version=3.0.1.2";//客户端来源 【选填】
    String it_b_pay = "10m";//  未付款交易的超时时间  【选填】 超时,该笔交易就会自动被关闭,用户输入支付密码、点击确认付款后(即创建支付宝交易后)开始计时。取值范围:1m~15d m-分钟,h-小时,d-天
    //extern_token 授权令牌 【选填】
    //out_context 商户业务扩展参数【x选填】

    //把请求参数打包成数组
    Map<String, String> sParaTemp = new TreeMap<String, String>();
    sParaTemp.put("service", "mobile.securitypay.pay");
    sParaTemp.put("partner", PayOnlineConstants.PARTNER);
    sParaTemp.put("seller_id", PayOnlineConstants.SELLER_EMAIL);
    sParaTemp.put("_input_charset", PayOnlineConstants.INPUT_CHARSET);
    sParaTemp.put("payment_type", payment_type);
    sParaTemp.put("notify_url", notify_url);
    sParaTemp.put("out_trade_no", out_trade_no);
    sParaTemp.put("subject", subject);
    sParaTemp.put("total_fee", total_fee);
    sParaTemp.put("body", body);
    sParaTemp.put("appenv", appenv);
    sParaTemp.put("it_b_pay", it_b_pay);
    String signStr = RSA.sign(AlipayCore.createLinkString(sParaTemp), PayOnlineConstants.PRIVATE_KEY, PayOnlineConstants.INPUT_CHARSET);

    System.out.println(signStr);
}


/*
 支付宝 支付结果异步通知服务器
     如果没有收到该页面返回的 success 信息,支付宝会在24小时内按一定的时间策略重发通知
     商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,并判断total_fee是否确实为该订单的实际金额
    (即商户订单创建时的金额),同时需要校验通知中的seller_id(或者seller_email) 
    是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
    上述有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。在上述验证通过后商户必须根据支付宝不同类型的业务通知,
    正确的进行不同的业务处理,并且过滤重复的通知结果数据。在支付宝的业务通知中,
    只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功
*/
@RequestMapping("/alipay/payNotify")
public void alipayPayNotify(HttpServletRequest request,HttpServletResponse response) throws AppException, IOException{
    //获取支付宝POST过来反馈信息
    Map<String,String> params = new HashMap<String,String>();
    Map requestParams = request.getParameterMap();
    for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
        String name = (String) iter.next();
        String[] values = (String[]) requestParams.get(name);
        String valueStr = "";
        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"), "gbk");
        params.put(name, valueStr);
    }

    //商户订单号 String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
    //支付宝交易号 String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
    //交易状态
    String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
    if(AlipayPayNotify.verify(params)){//验证成功
        //请在这里加上商户的业务逻辑程序代码

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

        if(trade_status.equals("TRADE_FINISHED")){
            //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //如果有做过处理,不执行商户的业务程序

            //注意:
            //退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
            //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
        } else if (trade_status.equals("TRADE_SUCCESS")){
            //判断该笔订单是否在商户网站中已经做过处理
                //如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
                //如果有做过处理,不执行商户的业务程序

            //注意:
            //付款完成后,支付宝系统发送该交易状态通知
            //请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
        }

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

        response.getWriter().println("success");    //请不要修改或删除
    }else{//验证失败
        response.getWriter().println("fail");
    }
}


/*
 支付宝 单笔交易查询
    支付宝交易号与商户网站订单号不能同时为空
*/
@RequestMapping("/alipay/query")
public void alipayQuery(HttpServletRequest request,HttpServletResponse response) throws Exception{
    //String trade_no = "";//支付宝交易号
    String out_trade_no = "1123233213";//商户订单号

    //把请求参数打包成数组
    Map<String, String> sParaTemp = new TreeMap<String, String>();
    sParaTemp.put("service", PayOnlineConstants.ALI_ORDER_QUERY);
    sParaTemp.put("partner", PayOnlineConstants.PARTNER);
    sParaTemp.put("_input_charset", PayOnlineConstants.INPUT_CHARSET);
    sParaTemp.put("out_trade_no", out_trade_no);

    //建立请求
    String sHtmlText = AlipaySubmit.buildRequest("", "", sParaTemp);
    response.getWriter().println(XMLUtil.doXMLParse(sHtmlText));

    log.info("【支付宝订单查询】"+XMLUtil.doXMLParse(sHtmlText));
}


/*
 支付宝 即时到账批量退款有密

@RequestMapping("/alipay/refund")
public void alipayRefund(HttpServletRequest request,HttpServletResponse response) throws Exception{
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
    String out_trade_no = "1123233213";//商户订单号

    String notify_url = PayOnlineConstants.ALI_REFUND_NOTIFY_URL;//异步通知服务器地址
    String seller_email = PayOnlineConstants.SELLER_EMAIL;//卖家支付宝帐户 必填
    String refund_date = sdf.format(new Date());//退款当天日期 必填,如:2007-10-01 13:13:13
    String batch_no = sdf2.format(new Date())+out_trade_no;//批次号 必填,格式:当天日期[8位]+序列号[3至24位],如:201008010000001
    String batch_num = "1";//退款笔数
    String detail_data = "2011011201037066^5.00^协商退款";//退款详细数据 原付款支付宝交易号^退款总金额^退款理由

    //把请求参数打包成数组
    Map<String, String> sParaTemp = new HashMap<String, String>();
    sParaTemp.put("service", PayOnlineConstants.ALI_ORDER_REFUND);
    sParaTemp.put("partner", PayOnlineConstants.PARTNER);
    sParaTemp.put("_input_charset", PayOnlineConstants.INPUT_CHARSET);
    sParaTemp.put("notify_url", notify_url);
    sParaTemp.put("seller_email", seller_email);
    sParaTemp.put("seller_user_id", PayOnlineConstants.PARTNER);
    sParaTemp.put("refund_date", refund_date);
    sParaTemp.put("batch_no", batch_no);
    sParaTemp.put("batch_num", batch_num);
    sParaTemp.put("detail_data", detail_data);

    //建立请求
    String sHtmlText = AlipaySubmit.buildRequest("", "", sParaTemp);
    response.getWriter().println(sHtmlText);

    log.info("【支付宝批量退款有密】"+sHtmlText);
}



 支付宝 退款结果异步通知服务器
     如果没有收到该页面返回的 success 信息,支付宝会在24小时内按一定的时间策略重发通知

@RequestMapping("/alipay/refundNotify")
public void alipayRefundNotify(HttpServletRequest request,HttpServletResponse response) throws AppException, IOException{
    //获取支付宝POST过来反馈信息
    Map<String,String> params = new HashMap<String,String>();
    Map requestParams = request.getParameterMap();
    for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
        String name = (String) iter.next();
        String[] values = (String[]) requestParams.get(name);
        String valueStr = "";
        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"), "gbk");
        params.put(name, valueStr);
    }

    //获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
    //批次号
    String batch_no = new String(request.getParameter("batch_no").getBytes("ISO-8859-1"),"UTF-8");
    //批量退款数据中转账成功的笔数
    String success_num = new String(request.getParameter("success_num").getBytes("ISO-8859-1"),"UTF-8");
    //批量退款数据中的详细信息
    String result_details = new String(request.getParameter("result_details").getBytes("ISO-8859-1"),"UTF-8");
    if(AlipayRefundNotify.verify(params)){//验证成功
        //请在这里加上商户的业务逻辑程序代码

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

        //判断是否在商户网站中已经做过了这次通知返回的处理
        //如果没有做过处理,那么执行商户的业务程序
        //如果有做过处理,那么不执行商户的业务程序

        response.getWriter().println("success");    //请不要修改或删除

        //——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
    }else{//验证失败
        response.getWriter().println("fail");
    }
}*/




//*********************************微信整理方法***************************************

//微信支付 生成在线支付记录
public void insertTradeOrderPayment(String payType,TradeOrder tradeOrder){  
    TradeOrderPayment tradeOrderPayment = new TradeOrderPayment();

    tradeOrderPayment.setOrderId(tradeOrder.getId());
    tradeOrderPayment.setPayType(payType); 
    tradeOrderPayment.setTotalFee(((Float)(tradeOrder.getPaidPrice()*100)).intValue());
    tradeOrderPayment.setStatus(TradeOrderPayStatus.N.name());

    tradeOrderPaymentService.save(tradeOrderPayment);
}

//微信支付 生成预支付ID prepayId
public Map<String,String> createPrepayId(TradeOrder tradeOrder,HttpServletRequest request) throws IOException{
    Map<String,String> map = new HashMap<String,String>();

    //准备参数
    SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
    String boy = "购买"+tradeOrder.getQuantity()+"件商品";//商品描述
    String loginIp = BrowserUtils.getAddress(request);//买家ip
    Float totalFee = tradeOrder.getPaidPrice();//买家实付金额
    String timeStart = format.format(new Date());//交易起始时间
    String timeExpire = format.format(new Date(new Date().getTime()+30*60*1000));//交易结束时间 定为30分钟

    //set参数
    Map<String,String> paramsMap = new TreeMap<String,String>();
    paramsMap.put("appid", PayOnlineConstants.APP_ID);
    paramsMap.put("body", boy);
    paramsMap.put("mch_id", PayOnlineConstants.MCH_ID);
    paramsMap.put("nonce_str", WXUtil.getNonceStr());
    paramsMap.put("notify_url", PayOnlineConstants.NOTIFY_URL);
    paramsMap.put("out_trade_no", tradeOrder.getId());
    paramsMap.put("spbill_create_ip", loginIp);
    paramsMap.put("total_fee", String.valueOf(((Float)(totalFee*100)).intValue()));
    paramsMap.put("time_start", timeStart);
    paramsMap.put("time_expire", timeExpire);
    paramsMap.put("trade_type", PayOnlineConstants.TRADE_TYPR);
    paramsMap.put("sign", WXUtil.getSign(paramsMap));

    TenpayHttpClientUtil httpClient = new TenpayHttpClientUtil();
    if (httpClient.callHttpPost(PayOnlineConstants.ORDER_URL, WXUtil.getParams(paramsMap))) {
        String resContent = httpClient.getResContent();
        try {
            //获取返回数据集合
            Map<String,String> returnMap = XMLUtil.doXMLParse(resContent);

            TradeOrderPayment topay = new TradeOrderPayment();
            topay.setOrderId(tradeOrder.getId());

            String returnCode = returnMap.get("return_code");//返回状态 SUCCESS/FAIL
            String returnMsg = returnMap.get("return_msg");//返回信息   

            if("SUCCESS".equals(returnCode)){
                String resultCode = returnMap.get("return_code");//业务结果 SUCCESS/FAIL
                topay.setResultCode(resultCode);

                if("SUCCESS".equals(resultCode)){//生成预支付id成功
                    String prepayId = returnMap.get("prepay_id");
                    topay.setPrepayId(prepayId);
                    topay.setPayCreatedTime(new Date());

                    log.info("【生成预支付id成功,订单号="+tradeOrder.getId()+"】");

                    map.put("resultCode","SUCCESS");
                    map.put("prepayId",prepayId);
                }else{
                    String errCode = returnMap.get("err_code");//错误代码
                    String errCodeDes = returnMap.get("err_code_des");//错误代码描述  
                    topay.setErrCode(errCode);
                    topay.setErrCodeDes(errCodeDes);

                    log.warn("【生成预支付id失败,订单号="+tradeOrder.getId()+",错误信息:"+errCodeDes+"】");
                    map.put("resultCode","ERROR");
                    map.put("message","生成预支付id失败,"+errCodeDes);
                }
            }else{  
                topay.setErrCodeDes(returnMsg);

                log.warn("【生成预支付id失败,订单号="+tradeOrder.getId()+",错误信息:"+returnMsg+"】");
                map.put("resultCode","ERROR");
                map.put("message","生成预支付id失败,"+returnMsg);
            }

            //修改订单支付表状态
            tradeOrderPaymentService.updateByOrderId(topay);

        } catch (JDOMException e) {
            e.printStackTrace();
        }
    }

    return map;
}

//微信支付 为app端调起支付准备参数
public Map<String,String> prepareParmaForApp(String prepayId){  
    Map<String,String> paramMap = new TreeMap<String,String>();

    //set参数
    paramMap.put("appid", PayOnlineConstants.APP_ID);
    paramMap.put("noncestr", WXUtil.getNonceStr());
    paramMap.put("package", "Sign=WXPay");
    paramMap.put("partnerid", PayOnlineConstants.MCH_ID);
    paramMap.put("prepayid", prepayId);
    paramMap.put("timestamp",String.valueOf(System.currentTimeMillis()/1000));
    paramMap.put("sign", WXUtil.getSign(paramMap));

    return paramMap;
}


//微信支付 查询订单
@SuppressWarnings("unchecked")
public Map<String,String> wzQuery(String orderId) throws AppException, IOException{ 
    Map<String,String> map = new HashMap<String,String>();

    //set参数
    Map<String,String> paramsMap = new TreeMap<String,String>();
    paramsMap.put("appid", PayOnlineConstants.APP_ID);
    paramsMap.put("mch_id", PayOnlineConstants.MCH_ID);
    paramsMap.put("nonce_str", WXUtil.getNonceStr());
    paramsMap.put("out_trade_no", orderId);//微信订单号 和 商户订单号 二选一  
    paramsMap.put("sign", WXUtil.getSign(paramsMap));

    TenpayHttpClientUtil httpClient = new TenpayHttpClientUtil();
    if (httpClient.callHttpPost(PayOnlineConstants.ORDER_QUERY, WXUtil.getParams(paramsMap))) {
        String resContent = httpClient.getResContent();
        try {
            //获取返回数据集合
            Map<String,String> returnMap = XMLUtil.doXMLParse(resContent);
            String returnCode = returnMap.get("return_code");
            String returnMsg = returnMap.get("return_msg");
            String resultCode = returnMap.get("result_code");

            if("SUCCESS".equals(returnCode)){
                if("SUCCESS".equals(resultCode)){
                    log.info("【查询订单成功,订单号="+orderId+"】");

                    //获取该订单支付情况
                    TradeOrderPayment tradeOrderPayment = tradeOrderPaymentService.selectByOrderId(orderId);
                    String payStatus = tradeOrderPayment.getStatus();

                    //微信端 支付结果情况
                    String tradeState = returnMap.get("trade_state");

                    map.put("resultCode","SUCCESS");
                    map.put("payStatus",payStatus);
                    map.put("tradeState",tradeState);
                }else{
                    log.warn("【查询订单失败,订单号="+orderId+",错误信息:"+returnMap.get("err_code_des")+"】");
                    map.put("resultCode","ERROR");
                    map.put("message","查询订单失败,"+returnMap.get("err_code_des"));
                }   
            }else{
                log.warn("【查询订单错误,订单号="+orderId+",错误信息:"+returnMsg+"】");
                map.put("resultCode","ERROR");
                map.put("message","查询订单失败,"+returnMsg);
            }
        } catch (JDOMException e) {
            e.printStackTrace();
        }
    }

    return map;
}

/*
  微信关闭订单
    以下情况需要调用关单接口:
    商户订单支付失败需要生成新单号重新发起支付,要对原订单号调用关单,避免重复支付;系统下单后,用户支付超时,系统退出不再受理,避免用户继续,请调用关单接口。
    注意:订单生成后不能马上调用关单接口,最短调用时间间隔为5分钟。
*/
@SuppressWarnings("unchecked")
public Map<String,String> wzClose(String orderId) throws AppException, IOException{
    Map<String,String> map = new HashMap<String,String>();

    //set参数
    Map<String,String> paramsMap = new TreeMap<String,String>();
    paramsMap.put("appid", PayOnlineConstants.APP_ID);
    paramsMap.put("mch_id", PayOnlineConstants.MCH_ID);
    paramsMap.put("nonce_str", WXUtil.getNonceStr());
    paramsMap.put("out_trade_no", orderId);
    paramsMap.put("sign", WXUtil.getSign(paramsMap));

    TenpayHttpClientUtil httpClient = new TenpayHttpClientUtil();
    if (httpClient.callHttpPost(PayOnlineConstants.ORDER_CLOSE, WXUtil.getParams(paramsMap))) {
        String resContent = httpClient.getResContent();
        try {
            //获取返回数据集合
            Map<String,String> returnMap = XMLUtil.doXMLParse(resContent);
            String returnCode = returnMap.get("return_code");
            String returnMsg = returnMap.get("return_msg");

            if("SUCCESS".equals(returnCode)){
                log.info("【关闭订单成功,订单号="+orderId+"】");
                map.put("resultCode","SUCCESS");
            }else{
                log.warn("【关闭订单失败,订单号="+orderId+",错误信息:"+returnMsg+"】");
                map.put("resultCode","ERROR");
                map.put("message","关闭订单失败,"+returnMsg);
            }
        } catch (JDOMException e) {
            e.printStackTrace();
        }
    }

    return map;
}

}

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页