Java支付宝二维码支付和退款,微信二维码支付

在蚂蚁金服开发平台下载demo
在这里插入图片描述
打开 TradePayDemo 项目,里面的main可以直接运行,在配置文件zfbinfo.properties中改为自己支付宝的信息

# 支付宝网关名、partnerId和appId
open_api_domain = https://openapi.alipay.com/gateway.do
mcloud_api_domain =
pid = 
appid = #申请应用并签约后会有一个有效的appid,应用名称一个月只能修改一次

# RSA私钥、公钥和支付宝公钥
private_key = 
public_key =   #这里的公钥为支付宝产生的应用公钥

#SHA1withRsa对应支付宝公钥
alipay_public_key = 

# 签名类型: RSA->SHA1withRsa,RSA2->SHA256withRsa
sign_type = RSA2
# 当面付最大查询次数和查询间隔(毫秒)
max_query_retry = 5
query_duration = 5000

# 当面付最大撤销次数和撤销间隔(毫秒)
max_cancel_retry = 3
cancel_duration = 2000

# 交易保障线程第一次调度延迟和调度间隔(秒)
heartbeat_delay = 5
heartbeat_duration = 900

二维码预下单,修改必要信息即可直接运行

package com.ys.demo.serviceImpl;

import com.alipay.api.*;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.ExtendParams;
import com.alipay.demo.trade.model.GoodsDetail;
import com.alipay.demo.trade.model.builder.AlipayTradePrecreateRequestBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPrecreateResult;
import com.alipay.demo.trade.service.AlipayMonitorService;
import com.alipay.demo.trade.service.AlipayTradeService;
import com.alipay.demo.trade.service.impl.AlipayMonitorServiceImpl;
import com.alipay.demo.trade.service.impl.AlipayTradeServiceImpl;
import com.alipay.demo.trade.service.impl.AlipayTradeWithHBServiceImpl;
import com.ys.demo.domain.Order;
import com.ys.demo.service.AlipayService;
import com.ys.demo.utils.payUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;


@Service
public class AlipayServiceImpl implements AlipayService {

    private static Log log = LogFactory.getLog(AlipayServiceImpl.class);

    // 支付宝当面付2.0服务
    private static AlipayTradeService tradeService;
    // 支付宝当面付2.0服务(集成了交易保障接口逻辑)
    @SuppressWarnings("unused")
	private static AlipayTradeService   tradeWithHBService;

    // 支付宝交易保障接口服务,供测试接口api使用,请先阅读readme.txt
    @SuppressWarnings("unused")
	private static AlipayMonitorService monitorService;
    static {
        /** 一定要在创建AlipayTradeService之前调用Configs.init()设置默认参数
         *  Configs会读取classpath下的zfbinfo.properties文件配置信息,如果找不到该文件则确认该文件是否在classpath目录
         */
        Configs.init("zfbinfo.properties");

        /** 使用Configs提供的默认参数
         *  AlipayTradeService可以使用单例或者为静态成员对象,不需要反复new
         */
        tradeService = new AlipayTradeServiceImpl.ClientBuilder().build();

        // 支付宝当面付2.0服务(集成了交易保障接口逻辑)
        tradeWithHBService = new AlipayTradeWithHBServiceImpl.ClientBuilder().build();

        /** 如果需要在程序中覆盖Configs提供的默认参数, 可以使用ClientBuilder类的setXXX方法修改默认参数 否则使用代码中的默认设置 */
        monitorService = new AlipayMonitorServiceImpl.ClientBuilder()
                .setGatewayUrl("http://mcloudmonitor.com/gateway.do").setCharset("GBK")
                .setFormat("json").build();
    }
    /**
     * 支付宝二维码
     * @param order
     * @author joke
     */
    @Override
    public String aliPay(Order order) throws Exception {

            // (必填) 商户网站订单系统中唯一订单号,64个字符以内,只能包含字母、数字、下划线,
            String outTradeNo = order.getOrderId();
            // (必填) 订单标题,粗略描述用户的支付目的。如“xxx品牌xxx门店当面付扫码消费”
            String subject = "消费";

            // (必填) 订单总金额,单位为元,不能超过1亿元
            // 如果同时传入了【打折金额】,【不可打折金额】,【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
            String totalAmount = String.valueOf(order.getPrice());//总金额,单位元
            // (可选) 订单不可打折金额,可以配合商家平台配置折扣活动,如果酒水不参与打折,则将对应金额填写至此字段
            // 如果该值未传入,但传入了【订单总金额】,【打折金额】,则该值默认为【订单总金额】-【打折金额】
            String undiscountableAmount = "0";

            // 卖家支付宝账号ID,用于支持一个签约账号下支持打款到不同的收款账号,(打款到sellerId对应的支付宝账号)
            // 如果该字段为空,则默认为与支付宝签约的商户的PID,也就是appid对应的PID
            String sellerId = "";

            // 订单描述,可以对交易或商品进行一个详细地描述,比如填写"购买商品2件共15.00元"
            String body = "消费";

            // 商户操作员编号,添加此参数可以为商户操作员做销售统计
            String operatorId = order.getOrderId();

            // (必填) 商户门店编号,通过门店号和商家后台可以配置精准到门店的折扣信息,详询支付宝技术支持
            String storeId = "test_store_id";

            // 业务扩展参数,目前可添加由支付宝分配的系统商编号(通过setSysServiceProviderId方法),详情请咨询支付宝技术支持
            ExtendParams extendParams = new ExtendParams();
            extendParams.setSysServiceProviderId("");

            // 支付超时,定义为1分钟
            String timeoutExpress = "1m";

            // 商品明细列表,需填写购买商品详细信息,
            List<GoodsDetail> goodsDetailList = new ArrayList<GoodsDetail>();
            // 创建一个商品信息,参数含义分别为商品id(使用国标)、名称、单价(单位为分)、数量,如果需要添加商品类别,详见GoodsDetail
            GoodsDetail goods1 = GoodsDetail.newInstance(order.getOrderId(), "消费", order.getPrice(), 1);
            // 创建好一个商品后添加至商品明细列表
            goodsDetailList.add(goods1);

            // 创建扫码支付请求builder,设置请求参数
            AlipayTradePrecreateRequestBuilder builder = new AlipayTradePrecreateRequestBuilder()
                    .setSubject(subject).setTotalAmount(totalAmount).setOutTradeNo(outTradeNo)
                    .setUndiscountableAmount(undiscountableAmount).setSellerId(sellerId).setBody(body)
                    .setOperatorId(operatorId).setStoreId(storeId).setExtendParams(extendParams)
                    .setTimeoutExpress(timeoutExpress)
                    .setNotifyUrl("")//支付宝回调地址
                    .setGoodsDetailList(goodsDetailList);

            AlipayF2FPrecreateResult result = tradeService.tradePrecreate(builder);
            String alipayUrl = null;
            switch (result.getTradeStatus()) {
                case SUCCESS:
                    log.info("支付宝预下单成功: )");

                    AlipayTradePrecreateResponse response = result.getResponse();
                    dumpResponse(response);
                    alipayUrl = response.getQrCode();

                    // 需要修改为运行机器上的路径
//                    String filePath = String.format("D:/qr-%s.png",
//                            response.getOutTradeNo());
//                    log.info("filePath:" + filePath);
//                                    ZxingUtils.getQRCodeImge(response.getQrCode(), 256, filePath);
                    break;

                case FAILED:
                    log.error("支付宝预下单失败!!!");
                    break;

                case UNKNOWN:
                    log.error("系统异常,预下单状态未知!!!");
                    break;

                default:
                    log.error("不支持的交易状态,交易返回异常!!!");
                    break;
            }
            return alipayUrl;
        }
    // 简单打印应答
    @Override
    public void dumpResponse(AlipayResponse response) {
        if (response != null) {
            log.info(String.format("code:%s, msg:%s", response.getCode(), response.getMsg()));
            if (StringUtils.isNotEmpty(response.getSubCode())) {
                log.info(String.format("subCode:%s, subMsg:%s", response.getSubCode(),
                        response.getSubMsg()));
            }
            log.info("body:" + response.getBody());
        }
    }

    /**
     * 支付宝退款
     * @param
     * @author joke
     */
    @Override
    public String refund(Order order) throws AlipayApiException{
        AlipayClient alipayClient = new DefaultAlipayClient(Configs.getOpenApiDomain(),Configs.getAppid(),Configs.getPrivateKey(),"json","UTF-8",Configs.getAlipayPublicKey(),"RSA2");
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":\"" + order.getOrderId() + "\"," +
                "\"refund_amount\":\"" + order.getPrice() + "\"," +
                "\"refund_currency\":\"" + payUtil.REFUND_FEE_TYPE + "\"," +
                "\"refund_reason\":\"" + payUtil.REFUND_DESC + "\"," +
                "\"out_request_no\":\"" + order.getOutRefundNo() + "\"," +
                "  }");
        AlipayTradeRefundResponse response = alipayClient.execute(request);
        String result = "success";
        if(response.isSuccess()){
            System.out.println("调用成功");
        } else {
            result = "failure";
            System.out.println("调用失败");
        }
        return result;
    }

    /**
     * 支付宝撤销
     * @param order
     * @author joke
     */
    @Override
    public String revoke(Order order)throws AlipayApiException {
        //AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do","app_id","your private_key","json","UTF-8","alipay_public_key","RSA2");
        AlipayClient alipayClient = new DefaultAlipayClient(Configs.getOpenApiDomain(),Configs.getAppid(),Configs.getPrivateKey(),"json","UTF-8",Configs.getAlipayPublicKey(),"RSA2");
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
        request.setBizContent("{" +
                "\"out_trade_no\":" + "\"" + order.getOrderId()+ "\"" + " }");
        String result = "1";
        AlipayTradeCancelResponse response = alipayClient.execute(request);
        if(response.isSuccess()){
            System.out.println("调用成功");
        } else {
            result = "0";
            System.out.println("调用失败");
        }

        return result;
    }


}

支付宝回调接口,ip需与域名绑定

package com.ys.demo.controller;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayApiException;
import com.alipay.api.internal.util.AlipaySignature;
import com.ys.demo.domain.Order;
import com.ys.demo.service.OrderService;
import com.ys.demo.serviceImpl.MQTTPublish;
import com.ys.demo.utils.AlipayConfig;
import com.ys.demo.utils.AlipayNotifyParam;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

@RestController
public class AlipayCallbackController {
    private static Log logger = LogFactory.getLog(AlipayCallbackController.class);

    @Autowired
    private AlipayConfig alipayConfig; // 支付宝支付配置

    @Autowired
    private OrderService orderService;

    @Autowired
    private MQTTPublish mqttPublish;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private ExecutorService executorService = Executors.newFixedThreadPool(20);
    @RequestMapping("alipayTest")
    public String method(){
        logger.info("Alipay callback!");
        return "Alipay callback!";
    }

    /**
     * <pre>
     * 第一步:验证签名,签名通过后进行第二步
     * 第二步:按一下步骤进行验证
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
     * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
     * 3、校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
     * </pre>
     *
     * @param request
     * @return
     */
    @RequestMapping("alipayCallback")
    public String callback(HttpServletRequest request) throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Map<String, String> params = convertRequestParamsToMap(request); // 将异步通知中收到的待验证所有参数都存放到map中
        String paramsJson = JSON.toJSONString(params);///支付宝回调的参数
        logger.info("支付宝回调,{}", new Throwable(paramsJson));
		String trade_status = params.get("trade_status");支付返回结果
            try {
                // 调用SDK验证签名
                boolean signVerified = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipay_public_key(),
                        alipayConfig.getCharset(), alipayConfig.getSigntype());
                if (signVerified) {
                    logger.info("支付宝回调签名认证成功");
                    // 按照支付结果异步通知中的描述,对支付结果中的业务内容进行1/2/3/4二次校验,校验成功后在response中返回success,校验失败返回failure
                    this.check(params);
                    // 另起线程处理业务
                    executorService.execute(new Runnable() {
                        @Override
                        public void run() {
                            
                            try{
                                // 支付成功业务逻辑处理
                                if ("TRADE_SUCCESS".equals(trade_status) || "TRADE_FINISHED".equals(trade_status)) {
                                   /业务逻辑处理
                                } else {
                                    ///业务逻辑处理
                                }
                            }catch (Exception e){
                                logger.error("Business handling exception!");
                            }
                        }
                    });
                    return "success";
                } else {
                    logger.info("支付宝回调签名认证失败,signVerified=false, paramsJson:{}"+ paramsJson);
                    //认证签名失败,业务逻辑处理
                    return "failure";
                }
            } catch (AlipayApiException e) {
                logger.error("支付宝回调签名认证失败,paramsJson:{},errorMsg:{}"+ paramsJson, e);
            }
        }

    // 将request中的参数转换成Map
    private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
        Map<String, String> retMap = new HashMap<String, String>();

        Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();

        for (Map.Entry<String, String[]> entry : entrySet) {
            String name = entry.getKey();
            String[] values = entry.getValue();
            int valLen = values.length;

            if (valLen == 1) {
                retMap.put(name, values[0]);
            } else if (valLen > 1) {
                StringBuilder sb = new StringBuilder();
                for (String val : values) {
                    sb.append(",").append(val);
                }
                retMap.put(name, sb.toString().substring(1));
            } else {
                retMap.put(name, "");
            }
        }

        return retMap;
    }

    private AlipayNotifyParam buildAlipayNotifyParam(Map<String, String> params) {
        String json = JSON.toJSONString(params);
        return JSON.parseObject(json, AlipayNotifyParam.class);
    }

    /**
     * 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
     * 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
     * 3、校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
     * 4、验证app_id是否为该商户本身。上述1、2、3、4有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
     * 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
     * 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
     *
     * @param params
     * @throws AlipayApiException
     */
    private void check(Map<String, String> params) throws AlipayApiException {
        String outTradeNo = params.get("out_trade_no");
        // 1、商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
        Order order = orderService.selectByOrderId(outTradeNo);
        if (order == null) {
            logger.error("out_trade_no错误" + sdf);
            throw new AlipayApiException("out_trade_no错误");
        }
        // 2、判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
        // 3、校验通知中的seller_id(或者seller_email)是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
        // 第三步可根据实际情况省略
        // 4、验证app_id是否为该商户本身。
        if (!params.get("app_id").equals(alipayConfig.getAppid())) {
            logger.error(outTradeNo + ",app_id不一致" + sdf);
            throw new AlipayApiException("app_id不一致");
        }
    }
    public MqttMessage getMsg(MqttMessage msg, String jsonS) {
        msg.setQos(1);
        msg.setRetained(true);
        msg.setPayload(jsonS.getBytes());
        return msg;
    }
}

微信二维码支付

package com.ys.demo.serviceImpl;


import com.google.zxing.BarcodeFormat;
import com.google.zxing.EncodeHintType;
import com.google.zxing.MultiFormatWriter;
import com.google.zxing.WriterException;
import com.google.zxing.common.BitMatrix;
import com.ys.demo.domain.Order;
import com.ys.demo.service.WeChatService;
import com.ys.demo.utils.wechat.*;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.util.Hashtable;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

@Service
public class WeChatServiceImpl implements WeChatService {
    private WXPayConstants.SignType signType;
    private boolean autoReport;
    private boolean useSandbox;
    @SuppressWarnings("unused")
	private String notifyUrl;
    private WXPayRequest wxPayRequest;
    /**
     * 作用:预下单<br>
     * 场景:扫码支付<br>
     * @param order 读超时时间,单位是毫秒
     * @return API返回数据
     * @throws Exception
     */
	@Override
	public String weixinPay(Order order) throws Exception {
		try{
            //String out_trade_no = "" + System.currentTimeMillis(); //订单号 (调整为自己的生产逻辑)

            // 账号信息
            String appid = PayConfigUtil.APP_ID;  // appid
            //String appsecret = PayConfigUtil.APP_SECRET; // appsecret
            String mch_id = PayConfigUtil.MCH_ID; // 商业号
            String key = PayConfigUtil.API_KEY; // key

            String currTime = PayToolUtil.getCurrTime();
            String strTime = currTime.substring(8, currTime.length());
            String strRandom = PayToolUtil.buildRandom(4) + "";
            String nonce_str = strTime + strRandom;

            // 获取发起电脑 ip
            String spbill_create_ip = PayConfigUtil.CREATE_IP;
            // 回调接口
            String notify_url = PayConfigUtil.NOTIFY_URL;
            String trade_type = "NATIVE";
            SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
            packageParams.put("appid", appid);
            packageParams.put("mch_id", mch_id);
            packageParams.put("nonce_str", nonce_str);
            packageParams.put("body", "消费");  //(调整为自己的名称)
            packageParams.put("out_trade_no", order.getOrderId());
            packageParams.put("total_fee", String.valueOf(order.getPrice())); //价格的单位为分
            packageParams.put("spbill_create_ip", spbill_create_ip);
            packageParams.put("notify_url", notify_url);
            packageParams.put("trade_type", trade_type);
            //packageParams.put("", "");
            String sign = PayToolUtil.createSign("UTF-8", packageParams,key); //签名
            packageParams.put("sign", sign);
            String requestXML = PayToolUtil.getRequestXml(packageParams); //将请求参数转换为xml格式的string
            String resXml = HttpUtil.postData(PayConfigUtil.UFDODER_URL, requestXML);  //连接微信,并返回result
            @SuppressWarnings("rawtypes")
			Map map = XMLUtil4jdom.doXMLParse(resXml);
            String urlCode = (String) map.get("code_url");
//            QRUtil.qwqe(urlCode);
            return urlCode;
        }catch (Exception e){
		    System.out.println("ss"+ e.getMessage());
        }
        return  null;
	}

    public void qrcode(String code) throws Exception {
        try {
            int width = 300;
            int height = 300;
            //二维码的图片格式
            String format = "gif";
            Hashtable hints = new Hashtable();
            //内容所使用编码
            hints.put(EncodeHintType.CHARACTER_SET, "utf-8");
            BitMatrix bitMatrix;
            try {
                bitMatrix = new MultiFormatWriter().encode(code, BarcodeFormat.QR_CODE, width, height, hints);
                File file = new File("d:"+File.separator+"new.gif");
//                QRUtil.writeToStream(bitMatrix, format, file);
            } catch (WriterException e) {
                e.printStackTrace();
            }

        } catch (Exception e) {
        }
    }

    /**
     * 作用:申请退款<br>
     * 场景:刷卡支付、公共号支付、扫码支付、APP支付<br>
     * 其他:需要证书
     * @param reqData 向wxpay post的请求数据
     * @param connectTimeoutMs 连接超时时间,单位是毫秒
     * @param readTimeoutMs 读超时时间,单位是毫秒
     * @return API返回数据
     * @throws Exception
     */
    @Override
    public String refund(Map<String, String> reqData, int connectTimeoutMs, int readTimeoutMs) throws Exception {
        String url;
        if (this.useSandbox) {
            url = WXPayConstants.SANDBOX_REFUND_URL_SUFFIX;
        }
        else {
            url = WXPayConstants.REFUND_URL_SUFFIX;
        }
        String respXml = this.requestWithCert(url, this.fillRequestData(reqData), connectTimeoutMs, readTimeoutMs);
        return this.processResponseXml(respXml);
    }
    /**
     * 向 Map 中添加 appid、mch_id、nonce_str、sign_type、sign <br>
     * 该函数适用于商户适用于统一下单等接口,不适用于红包、代金券接口
     *
     * @param reqData
     * @return
     * @throws Exception
     */
    @Override
    public Map<String, String> fillRequestData(Map<String, String> reqData) throws Exception {
        //reqData.put("appid", config.getAppID());
        reqData.put("appid", PayConfigUtil.APP_ID);
        //reqData.put("mch_id", config.getMchID());
        reqData.put("mch_id", PayConfigUtil.MCH_ID);
        reqData.put("nonce_str", WXPayUtil.generateNonceStr());
        if (WXPayConstants.SignType.MD5.equals(this.signType)) {
            reqData.put("sign_type", WXPayConstants.MD5);
        }
        else if (WXPayConstants.SignType.HMACSHA256.equals(this.signType)) {
            reqData.put("sign_type", WXPayConstants.HMACSHA256);
        }
        //reqData.put("sign", WXPayUtil.generateSignature(reqData, config.getKey(), this.signType));
        reqData.put("sign", WXPayUtil.generateSignature(reqData, PayConfigUtil.API_KEY, this.signType));
        return reqData;
    }

    /**
     * 需要证书的请求
     * @param urlSuffix String
     * @param reqData 向wxpay post的请求数据  Map
     * @param connectTimeoutMs 超时时间,单位是毫秒
     * @param readTimeoutMs 超时时间,单位是毫秒
     * @return API返回数据
     * @throws Exception
     */
    @Override
    public String requestWithCert(String urlSuffix, Map<String, String> reqData,
                                  int connectTimeoutMs, int readTimeoutMs) throws Exception {
        String msgUUID= reqData.get("nonce_str");
        String reqBody = WXPayUtil.mapToXml(reqData);

        String resp = this.wxPayRequest.requestWithCert(urlSuffix, msgUUID, reqBody, connectTimeoutMs, readTimeoutMs, this.autoReport);
        return resp;
    }

    /**
     * 处理 HTTPS API返回数据,转换成Map对象。return_code为SUCCESS时,验证签名。
     * @param xmlStr API返回的XML格式数据
     * @return Map类型数据
     * @throws Exception
     */
//    @Override
//    public Map<String, String> processResponseXml(String xmlStr) throws Exception {
//        String RETURN_CODE = "return_code";
//        String return_code;
//        Map<String, String> respData = WXPayUtil.xmlToMap(xmlStr);
//        if (respData.containsKey(RETURN_CODE)) {
//            return_code = respData.get(RETURN_CODE);
//        }
//        else {
//            throw new Exception(String.format("No `return_code` in XML: %s", xmlStr));
//        }
//
//        if (return_code.equals(WXPayConstants.FAIL)) {
//            return respData;
//        }
//        else if (return_code.equals(WXPayConstants.SUCCESS)) {
//            if (this.isResponseSignatureValid(respData)) {
//                return respData;
//            }
//            else {
//                throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr));
//            }
//        }
//        else {
//            throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr));
//        }
//    }
    @Override
    public String processResponseXml(String xmlStr) throws Exception {
        String RETURN_CODE = "return_code";
        String return_code;
        Map<String, String> respData = WXPayUtil.xmlToMap(xmlStr);
        if (respData.containsKey(RETURN_CODE)) {
            return_code = respData.get(RETURN_CODE);
        }
        else {
            return "failure";
            //throw new Exception(String.format("No `return_code` in XML: %s", xmlStr));
        }

        if (return_code.equals(WXPayConstants.FAIL)) {
            return "failure";
        }
        else if (return_code.equals(WXPayConstants.SUCCESS)) {
            if (this.isResponseSignatureValid(respData)) {
                return "success";
            }
            else {
                return "failure";
                //throw new Exception(String.format("Invalid sign value in XML: %s", xmlStr));
            }
        }
        else {
            return "failure";
            //throw new Exception(String.format("return_code value %s is invalid in XML: %s", return_code, xmlStr));
        }
    }

    /**
     * 判断xml数据的sign是否有效,必须包含sign字段,否则返回false。
     *
     * @param reqData 向wxpay post的请求数据
     * @return 签名是否有效
     * @throws Exception
     */
    @Override
    public boolean isResponseSignatureValid(Map<String, String> reqData) throws Exception {
        // 返回数据的签名方式和请求中给定的签名方式是一致的
        return WXPayUtil.isSignatureValid(reqData, PayConfigUtil.API_KEY, this.signType);
    }
}

微信回调接口,域名和ip需绑定,否则不能回调

package com.ys.demo.controller;

import com.ys.demo.domain.Order;
import com.ys.demo.utils.wechat.PayConfigUtil;
import com.ys.demo.utils.wechat.PayToolUtil;
import com.ys.demo.utils.wechat.XMLUtil4jdom;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.ModelMap;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.*;

@RestController
public class PayCallBackController{
    private static Log logger = LogFactory.getLog(PayCallBackController.class);
//    @Autowired
//    private OrderService orderService;

    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    @RequestMapping("wxpayTtest")
    public String method(){
        logger.info("wxpay callback!");
        return "wxpay callback!";
    }
    /*
    * 微信回调函数
    * */
    @RequestMapping("weixinNotify")
    public void wechatCallBack(HttpServletRequest request, HttpServletResponse response,
                               ModelMap modelMap)  throws JDOMException, Exception{
        logger.info("微信回调");
        MqttMessage msg = new MqttMessage();
        //读取参数
        InputStream inputStream ;
        StringBuffer sb = new StringBuffer();
        inputStream = request.getInputStream();
        String s ;
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
        while ((s = in.readLine()) != null){
            sb.append(s);
        }
        in.close();
        inputStream.close();

        /* 解析xml成map */
        Map<String, String> m = new HashMap<String, String>();
        m = XMLUtil4jdom.doXMLParse(sb.toString());

        //过滤空 设置 TreeMap
        SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();
        Iterator it = m.keySet().iterator();
        while (it.hasNext()) {
            String parameter = (String) it.next();
            String parameterValue = m.get(parameter);

            String v = "";
            if(null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        // 账号信息
        String key = PayConfigUtil.API_KEY; //key
        String orderId = (String)packageParams.get("out_trade_no");

//        Order order = orderService.selectByOrderId(orderId);
//        if (StringUtils.isEmpty(order)){
//            return;
//        }
        String price = (String)packageParams.get("price");

        if(PayToolUtil.isTenpaySign("UTF-8", packageParams,key)) {
            String resXml = "";
            if("SUCCESS".equals((String)packageParams.get("result_code"))){
                //执行自己的业务逻辑
                request.getSession().setAttribute("_PAY_RESULT", "OK");
                //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了.
                resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"
                        + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";
            } else {
                //执行自己的业务逻辑
                resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"
                        + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";
            }
            BufferedOutputStream out = new BufferedOutputStream(
                    response.getOutputStream());
            out.write(resXml.getBytes());
            out.flush();
            out.close();
        } else{
            logger.error(sdf+"通知签名验证失败:"+packageParams);
        }
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值