mallplus多商户商城 让支付触手可及,封装了微信支付、QQ支付、支付宝支付、京东支付、银联支付常用的支付方式以及各种常用的接口

代码下载地址  https://gitee.com/zscat/mallplus

关注公众号获取微服务版本下载地址和部署方式

1,各种微信支付方式接口

package com.zscat.mallplus.pay.controller.wxpay;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import com.jfinal.kit.StrKit;
import com.zscat.mallplus.core.enums.SignType;
import com.zscat.mallplus.core.enums.TradeType;
import com.zscat.mallplus.core.kit.*;
import com.zscat.mallplus.enums.OrderStatus;
import com.zscat.mallplus.exception.ApiMallPlusException;
import com.zscat.mallplus.oms.entity.OmsOrder;
import com.zscat.mallplus.oms.entity.OmsPayments;
import com.zscat.mallplus.oms.service.IOmsOrderItemService;
import com.zscat.mallplus.oms.service.IOmsOrderService;
import com.zscat.mallplus.oms.service.IOmsPaymentsService;
import com.zscat.mallplus.pay.entity.H5SceneInfo;
import com.zscat.mallplus.pay.entity.WxPayBean;
import com.zscat.mallplus.pay.vo.AjaxResult;
import com.zscat.mallplus.ums.entity.SysAppletSet;
import com.zscat.mallplus.ums.entity.UmsMember;
import com.zscat.mallplus.ums.mapper.SysAppletSetMapper;
import com.zscat.mallplus.ums.service.IUmsMemberService;
import com.zscat.mallplus.util.JsonUtils;
import com.zscat.mallplus.utils.CommonResult;
import com.zscat.mallplus.wxpay.WxPayApi;
import com.zscat.mallplus.wxpay.WxPayApiConfig;
import com.zscat.mallplus.wxpay.model.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>mallplus Pay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
 *
 * <p>不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。 </p>
 *
 * <p>mallplus Pay 交流群: 320860169</p>
 *
 * <p>Node.js 版: https://gitee.com/javen205/TNW</p>
 *
 * <p>微信支付 Demo</p>
 *
 * @author Javen
 */
@RestController
@RequestMapping("api/wxPay")
public class WxPayController extends AbstractWxPayApiController {
    private static final String USER_PAYING = "USERPAYING";
    private Logger log = LoggerFactory.getLogger(this.getClass());
    @Resource
    private IOmsOrderService orderService;
    @Resource
    private IUmsMemberService umsMemberService;
    @Resource
    private IOmsOrderItemService orderItemService;
    @Autowired
    private IOmsPaymentsService paymentsService;
    @Resource
    private SysAppletSetMapper appletSetMapper;
    private String notifyUrl = "http://java.chengguo.link:8081/api";
    private String refundNotifyUrl;

    @Override
    public WxPayApiConfig getApiConfig() {
        WxPayApiConfig apiConfig = null;

        try {
            OmsPayments payments = paymentsService.getById(1);
            if (payments != null) {
                WxPayBean wxPayBean = JsonUtils.jsonToPojo(payments.getParams(), WxPayBean.class);
                apiConfig = WxPayApiConfig.builder()
                        .appId(wxPayBean.getAppId())
                        .mchId(wxPayBean.getMchId())
                        .partnerKey(wxPayBean.getPartnerKey())
                        .certPath(wxPayBean.getCertPath())
                        .domain(wxPayBean.getDomain())
                        .build();
            }
            notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify");
            refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify");
        } catch (Exception e) {
            WxPayBean wxPayBean = new WxPayBean();
            wxPayBean.setAppId("wx8321531c6046c924");
            wxPayBean.setMchId("1533901051");
            wxPayBean.setDomain("http://www.yjlive.cn/api/api");
            wxPayBean.setPartnerKey("shen9136shen9136shen9136shen9136");
            apiConfig = WxPayApiConfig.builder()
                    .appId(wxPayBean.getAppId())
                    .mchId(wxPayBean.getMchId())
                    .partnerKey(wxPayBean.getPartnerKey())
                    .certPath(wxPayBean.getCertPath())
                    .domain(wxPayBean.getDomain())
                    .build();

            notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify");
            refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify");
        }

        return apiConfig;
    }

    public WxPayApiConfig getApiConfig1() {
        WxPayApiConfig apiConfig = null;

        try {
            SysAppletSet appletSet = appletSetMapper.selectOne(new QueryWrapper<>());
            if (null == appletSet) {
                throw new ApiMallPlusException("没有设置支付配置");
            }
            if (appletSet != null) {
                apiConfig = WxPayApiConfig.builder()
                        .appId(appletSet.getAppid())
                        .mchId(appletSet.getMchid())
                        .partnerKey(appletSet.getPaySignKey())
                        .certPath(appletSet.getCertname())
                        .domain(appletSet.getNotifyurl())
                        .build();
            }
            notifyUrl = apiConfig.getDomain().concat("/wxPay/payNotify");
            refundNotifyUrl = apiConfig.getDomain().concat("/wxPay/refundNotify");
        } catch (Exception e) {

        }

        return apiConfig;
    }
    @GetMapping("/getKey")
    @ResponseBody
    public void getKey() {

        // return new CommonResult().success(WxPayApi.getSignKey(wxPayBean.getMchId(), wxPayBean.getPartnerKey(), SignType.MD5));
    }

    /**
     * 微信H5 支付
     * 注意:必须再web页面中发起支付且域名已添加到开发配置中
     */
    @RequestMapping(value = "/wapPay", method = {RequestMethod.POST, RequestMethod.GET})
    public Object wapPay(HttpServletRequest request, @RequestParam(value = "orderId", required = false, defaultValue = "0") Long orderId) throws IOException {
        try {
            String ip = IpKit.getRealIp(request);
            if (StrKit.isBlank(ip)) {
                ip = "127.0.0.1";
            }

            OmsOrder orderInfo = orderService.getById(orderId);
            if (null == orderInfo) {
                return new CommonResult().failed("订单已取消" );
            }
            if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
                return new CommonResult().failed( "订单已已关闭,请不要重复操作" );
            }
            if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
                return new CommonResult().failed( "订单已支付,请不要重复操作" );
            }

            H5SceneInfo sceneInfo = new H5SceneInfo();
            WxPayApiConfig wxPayApiConfig = this.getApiConfig1();

            H5SceneInfo.H5 h5_info = new H5SceneInfo.H5();
            h5_info.setType("Wap");
            //此域名必须在商户平台--"产品中心"--"开发配置"中添加
            h5_info.setWap_url(wxPayApiConfig.getDomain());
            h5_info.setWap_name("mallplus Pay VIP 充值");
            sceneInfo.setH5Info(h5_info);


            Map<String, String> params = UnifiedOrderModel
                    .builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .body("mallplus  微信H5 支付")
                    .attach(orderInfo.getStoreName())
                    .out_trade_no(orderInfo.getOrderSn())
                    .total_fee(orderInfo.getPayAmount().multiply(new BigDecimal(100)).intValue()+"")
                    .spbill_create_ip(ip)
                    .notify_url(notifyUrl)
                    .trade_type(TradeType.MWEB.getTradeType())
                    .scene_info(JSON.toJSONString(sceneInfo))
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
            log.info("params:"+params.toString());
            String xmlResult = WxPayApi.pushOrder(false, params);
            log.info("xmlResult:"+xmlResult);

            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

            String return_code = result.get("return_code");
            String return_msg = result.get("return_msg");
            if (!WxPayKit.codeIsOk(return_code)) {
                throw new RuntimeException(return_msg);
            }
            String result_code = result.get("result_code");
            if (!WxPayKit.codeIsOk(result_code)) {
                throw new RuntimeException(return_msg);
            }
            // 以下字段在return_code 和result_code都为SUCCESS的时候有返回

            String prepayId = result.get("prepay_id");
            String webUrl = result.get("mweb_url");

            log.info("prepay_id:" + prepayId + " mweb_url:" + webUrl);
            //   response.sendRedirect(webUrl);
            return new CommonResult().success(webUrl);
        }catch (Exception e){
            e.printStackTrace();
            return new CommonResult().failed(e.getMessage());
        }

    }

    /**
     * openId,采用 网页授权获取 access_token API:SnsAccessTokenApi获取
     */
    @RequestMapping(value = "/authCodeToOpenid", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object authCodeToOpenid(@RequestParam(value = "wxH5Appid", required = true, defaultValue = "0")String wxH5Appid,
                                   @RequestParam(value = "wxH5Secret", required = true, defaultValue = "0")String wxH5Secret,
                                   @RequestParam(value = "code", required = true, defaultValue = "0")String code) {
        return new CommonResult().success(umsMemberService.webLogin( wxH5Appid, wxH5Secret,  code));
    }

    /**
     * 公众号支付
     */
    @RequestMapping(value = "/webPay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object webPay(HttpServletRequest request, @RequestParam(value = "orderId", required = true, defaultValue = "0") Long orderId) {
        try {
            String totalFee = "0.01";
            // openId,采用 网页授权获取 access_token API:SnsAccessTokenApi获取
            UmsMember member = umsMemberService.getNewCurrentMember();
            String openId = member.getWeixinOpenid();
            if (StrUtil.isEmpty(openId)) {
                return new CommonResult().failed("openId is null");
            }
            if (StrUtil.isEmpty(totalFee)) {
                return new CommonResult().failed("请输入数字金额");
            }
            String ip = IpKit.getRealIp(request);
            if (StrUtil.isEmpty(ip)) {
                ip = "127.0.0.1";
            }

            OmsOrder orderInfo = orderService.getById(orderId);
            if (null == orderInfo) {
                return new CommonResult().failed("订单已取消" );
            }
            if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
                return new CommonResult().failed( "订单已已关闭,请不要重复操作" );
            }
            if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
                return new CommonResult().failed( "订单已支付,请不要重复操作" );
            }
            System.out.println(orderInfo.getPayAmount().multiply(new BigDecimal(100)).toPlainString());

            WxPayApiConfig wxPayApiConfig = this.getApiConfig();
            Map<String, String> params = UnifiedOrderModel
                    .builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .body("mallplus 公众号支付") // mallplus Pay 让支付触手可及-公众号支付
                    .attach(orderInfo.getStoreName())
                    .out_trade_no(orderInfo.getOrderSn())
                    .total_fee(orderInfo.getPayAmount().multiply(new BigDecimal(100)).intValue()+"")
                    .spbill_create_ip(ip)
                    .notify_url(notifyUrl)
                    .trade_type(TradeType.JSAPI.getTradeType())
                    .openid(openId)
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

            String xmlResult = WxPayApi.pushOrder(false, params);
            log.info("xmlResult:"+xmlResult);

            Map<String, String> resultMap = WxPayKit.xmlToMap(xmlResult);
            String returnCode = resultMap.get("return_code");
            String returnMsg = resultMap.get("return_msg");
            if (!WxPayKit.codeIsOk(returnCode)) {
                return new CommonResult().failed(returnMsg);
            }
            String resultCode = resultMap.get("result_code");
            if (!WxPayKit.codeIsOk(resultCode)) {
                return new CommonResult().failed(returnMsg);
            }

            // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回

            String prepayId = resultMap.get("prepay_id");

            Map<String, String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayApiConfig.getAppId(),
                    wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

            String jsonStr = JSON.toJSONString(packageParams);
            return new CommonResult().success(jsonStr);
        }catch (Exception e){
            e.printStackTrace();
            return new CommonResult().failed(e.getMessage());
        }

    }

    /**
     * 扫码模式一
     */
    @RequestMapping(value = "/scanCode1", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object scanCode1(HttpServletRequest request, HttpServletResponse response,
                            @RequestParam("productId") String productId) {
        try {
            if (StrKit.isBlank(productId)) {
                return new CommonResult().failed("productId is null");
            }
            WxPayApiConfig config = this.getApiConfig();
            //获取扫码支付(模式一)url
            String qrCodeUrl = WxPayKit.bizPayUrl(config.getPartnerKey(), config.getAppId(), config.getMchId(), productId);
            log.info(qrCodeUrl);
            //生成二维码保存的路径
            String name = "payQRCode1.png";
            log.info(ResourceUtils.getURL("classpath:").getPath());
            Boolean encode = QrCodeKit.encode(qrCodeUrl, BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H,
                    "png", 200, 200,
                    ResourceUtils.getURL("classpath:").getPath().concat("static").concat(File.separator).concat(name));
            if (encode) {
                //在页面上显示
                return new AjaxResult().success(name);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new CommonResult().failed("系统异常:" + e.getMessage());
        }
        return null;
    }

    /**
     * 扫码支付模式一回调
     */
    @RequestMapping(value = "/scanCodeNotify", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String scanCodeNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            String result = HttpKit.readData(request);
            log.info("scanCodeNotify>>>" + result);
            /**
             * 获取返回的信息内容中各个参数的值
             */
            Map<String, String> map = WxPayKit.xmlToMap(result);
            for (String key : map.keySet()) {
                log.info("key= " + key + " and value= " + map.get(key));
            }

            String appId = map.get("appid");
            String openId = map.get("openid");
            String mchId = map.get("mch_id");
            String isSubscribe = map.get("is_subscribe");
            String nonceStr = map.get("nonce_str");
            String productId = map.get("product_id");
            String sign = map.get("sign");

            Map<String, String> packageParams = new HashMap<String, String>(6);
            packageParams.put("appid", appId);
            packageParams.put("openid", openId);
            packageParams.put("mch_id", mchId);
            packageParams.put("is_subscribe", isSubscribe);
            packageParams.put("nonce_str", nonceStr);
            packageParams.put("product_id", productId);

            WxPayApiConfig wxPayApiConfig = this.getApiConfig();

            String packageSign = WxPayKit.createSign(packageParams, wxPayApiConfig.getPartnerKey(), SignType.MD5);

            String ip = IpKit.getRealIp(request);
            if (StrKit.isBlank(ip)) {
                ip = "127.0.0.1";
            }
            Map<String, String> params = UnifiedOrderModel
                    .builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .body("mallplus Pay 让支付触手可及-扫码支付模式一")
                    .attach("Node.js 版:https://gitee.com/javen205/TNW")
                    .out_trade_no(WxPayKit.generateStr())
                    .total_fee("1")
                    .spbill_create_ip(ip)
                    .notify_url(notifyUrl)
                    .trade_type(TradeType.NATIVE.getTradeType())
                    .openid(openId)
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
            String xmlResult = WxPayApi.pushOrder(false, params);
            log.info("统一下单:" + xmlResult);
            /**
             * 发送信息给微信服务器
             */
            Map<String, String> payResult = WxPayKit.xmlToMap(xmlResult);
            String returnCode = payResult.get("return_code");
            String resultCode = payResult.get("result_code");
            if (WxPayKit.codeIsOk(returnCode) && WxPayKit.codeIsOk(resultCode)) {
                // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
                String prepayId = payResult.get("prepay_id");

                Map<String, String> prepayParams = new HashMap<String, String>(10);
                prepayParams.put("return_code", "SUCCESS");
                prepayParams.put("appid", appId);
                prepayParams.put("mch_id", mchId);
                prepayParams.put("nonceStr", System.currentTimeMillis() + "");
                prepayParams.put("prepay_id", prepayId);
                String prepaySign = null;
                if (sign.equals(packageSign)) {
                    prepayParams.put("result_code", "SUCCESS");
                } else {
                    prepayParams.put("result_code", "FAIL");
                    //result_code为FAIL时,添加该键值对,value值是微信告诉客户的信息
                    prepayParams.put("err_code_des", "订单失效");
                }
                prepaySign = WxPayKit.createSign(prepayParams, wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
                prepayParams.put("sign", prepaySign);
                String xml = WxPayKit.toXml(prepayParams);
                log.error(xml);
                return xml;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 扫码支付模式二
     */
    @RequestMapping(value = "/scanCode2", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object scanCode2(HttpServletRequest request, HttpServletResponse response,
                            @RequestParam("total_fee") String totalFee) {

        if (StrKit.isBlank(totalFee)) {
            return new CommonResult().failed("支付金额不能为空");
        }

        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        WxPayApiConfig wxPayApiConfig = this.getApiConfig();

        Map<String, String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body("mallplus Pay 让支付触手可及-扫码支付模式二")
                .attach("Node.js 版:https://gitee.com/javen205/TNW")
                .out_trade_no(WxPayKit.generateStr())
                .total_fee("1")
                .spbill_create_ip(ip)
                .notify_url(notifyUrl)
                .trade_type(TradeType.NATIVE.getTradeType())
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.pushOrder(false, params);
        log.info("统一下单:" + xmlResult);

        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        System.out.println(returnMsg);
        if (!WxPayKit.codeIsOk(returnCode)) {
            return new CommonResult().failed("error:" + returnMsg);
        }
        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            return new CommonResult().failed("error:" + returnMsg);
        }
        //生成预付订单success

        String qrCodeUrl = result.get("code_url");
        String name = "payQRCode2.png";

        Boolean encode = QrCodeKit.encode(qrCodeUrl, BarcodeFormat.QR_CODE, 3, ErrorCorrectionLevel.H, "png", 200, 200,
                request.getSession().getServletContext().getRealPath("/") + File.separator + name);
        if (encode) {
            //在页面上显示
            return new AjaxResult().success(name);
        }
        return null;
    }

    /**
     * 刷卡支付
     */
    @RequestMapping(value = "/micropay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object microPay(HttpServletRequest request, HttpServletResponse response) {
        String authCode = request.getParameter("auth_code");
        String totalFee = request.getParameter("total_fee");
        if (StrKit.isBlank(totalFee)) {
            return new CommonResult().failed("支付金额不能为空");
        }
        if (StrKit.isBlank(authCode)) {
            return new CommonResult().failed("auth_code参数错误");
        }
        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }
        WxPayApiConfig wxPayApiConfig = this.getApiConfig();

        Map<String, String> params = MicroPayModel.builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .body("mallplus Pay 让支付触手可及-刷卡支付")
                .attach("Node.js 版:https://gitee.com/javen205/TNW")
                .out_trade_no(WxPayKit.generateStr())
                .total_fee("1")
                .spbill_create_ip(ip)
                .auth_code(authCode)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

        String xmlResult = WxPayApi.microPay(false, params);
        //同步返回结果
        log.info("xmlResult:" + xmlResult);
        Map<String, String> result = WxPayKit.xmlToMap(xmlResult);
        String returnCode = result.get("return_code");
        String returnMsg = result.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            //通讯失败
            String errCode = result.get("err_code");
            if (StrKit.notBlank(errCode)) {
                //用户支付中,需要输入密码
                if (USER_PAYING.equals(errCode)) {
                    //等待5秒后调用【查询订单API】
                }
            }
            log.info("提交刷卡支付失败>>" + xmlResult);
            return new CommonResult().failed(returnMsg);
        }

        String resultCode = result.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            log.info("支付失败>>" + xmlResult);
            String errCodeDes = result.get("err_code_des");
            return new CommonResult().failed(errCodeDes);
        }
        //支付成功
        return new AjaxResult().success(xmlResult);
    }

    /**
     * 微信APP支付
     */
    @RequestMapping(value = "/appPay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object appPay(HttpServletRequest request,@RequestParam(value = "orderId", required = false, defaultValue = "0") Long orderId) {

        try {
            String ip = IpKit.getRealIp(request);
            if (StrKit.isBlank(ip)) {
                ip = "127.0.0.1";
            }
            OmsOrder orderInfo = orderService.getById(orderId);
            if (null == orderInfo) {
                return new CommonResult().failed("订单已取消" );
            }
            if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
                return new CommonResult().failed( "订单已已关闭,请不要重复操作" );
            }
            if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
                return new CommonResult().failed( "订单已支付,请不要重复操作" );
            }
            WxPayApiConfig wxPayApiConfig = this.getApiConfig();

            Map<String, String> params = UnifiedOrderModel
                    .builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .body("微信APP支付")
                    .attach(orderInfo.getStoreName())
                    .out_trade_no(orderInfo.getOrderSn())
                    .total_fee(orderInfo.getPayAmount().multiply(new BigDecimal(100)).intValue()+"")
                    .spbill_create_ip(ip)
                    .notify_url(notifyUrl)
                    .trade_type(TradeType.APP.getTradeType())
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

            String xmlResult = WxPayApi.pushOrder(false, params);

            log.info(xmlResult);
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

            String returnCode = result.get("return_code");
            String returnMsg = result.get("return_msg");
            if (!WxPayKit.codeIsOk(returnCode)) {
                return new CommonResult().failed(returnMsg);
            }
            String resultCode = result.get("result_code");
            if (!WxPayKit.codeIsOk(resultCode)) {
                return new CommonResult().failed(returnMsg);
            }
            // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
            String prepayId = result.get("prepay_id");

            Map<String, String> packageParams = WxPayKit.appPrepayIdCreateSign(wxPayApiConfig.getAppId(), wxPayApiConfig.getMchId(), prepayId,
                    wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

            //  WxAppPayDto dto = JsonUtils.map2pojo(packageParams, WxAppPayDto.class);
            log.info("返回apk的参数:" + JsonUtils.objectToJson(packageParams));
            return new CommonResult().success(JsonUtils.objectToJson(packageParams));
        }catch (Exception e){
            e.printStackTrace();
            return new CommonResult().failed(e.getMessage());
        }

    }

    /**
     * 微信小程序支付
     */
    @RequestMapping(value = "/miniAppPay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public Object miniAppPay(HttpServletRequest request,@RequestParam(value = "orderId", required = false, defaultValue = "0") Long orderId) {
        try {
            //需要通过授权来获取openId
            UmsMember user = umsMemberService.getNewCurrentMember();

            String ip = IpKit.getRealIp(request);
            if (StrKit.isBlank(ip)) {
                ip = "127.0.0.1";
            }

            SysAppletSet appletSet = appletSetMapper.selectOne(new QueryWrapper<>());
            if (null == appletSet) {
                throw new ApiMallPlusException("没有设置支付配置");
            }
            OmsOrder orderInfo = orderService.getById(orderId);
            if (null == orderInfo) {
                return new CommonResult().failed("订单已取消" );
            }
            if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
                return new CommonResult().failed( "订单已已关闭,请不要重复操作" );
            }
            if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
                return new CommonResult().failed( "订单已支付,请不要重复操作" );
            }
            WxPayBean wxPayApiConfig = new WxPayBean();

            wxPayApiConfig.setAppId(appletSet.getAppid());
            wxPayApiConfig.setMchId(appletSet.getMchid());
            wxPayApiConfig.setDomain(appletSet.getNotifyurl());
            wxPayApiConfig.setPartnerKey(appletSet.getPaySignKey());

            Map<String, String> params = UnifiedOrderModel
                    .builder()
                    .appid(wxPayApiConfig.getAppId())
                    .mch_id(wxPayApiConfig.getMchId())
                    .nonce_str(WxPayKit.generateStr())
                    .body("mallplus-小程序支付")
                    .attach("Node.js 版:https://gitee.com/javen205/TNW")
                    .out_trade_no(orderInfo.getOrderSn())
                    .total_fee(orderInfo.getPayAmount().multiply(new BigDecimal(100)).intValue()+"")
                    .spbill_create_ip(ip)
                    .notify_url(notifyUrl)
                    .trade_type(TradeType.JSAPI.getTradeType())
                    .openid(user.getWeixinOpenid())
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);

            String xmlResult = WxPayApi.pushOrder(false, params);

            log.info(xmlResult);
            Map<String, String> result = WxPayKit.xmlToMap(xmlResult);

            String returnCode = result.get("return_code");
            String returnMsg = result.get("return_msg");
            if (!WxPayKit.codeIsOk(returnCode)) {
                return new CommonResult().failed(returnMsg);
            }
            String resultCode = result.get("result_code");
            if (!WxPayKit.codeIsOk(resultCode)) {
                return new CommonResult().failed(returnMsg);
            }
            // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回
            String prepayId = result.get("prepay_id");
            Map<String, String> packageParams = WxPayKit.miniAppPrepayIdCreateSign(wxPayApiConfig.getAppId(), prepayId,
                    wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256);
            String jsonStr = JSON.toJSONString(packageParams);
            log.info("小程序支付的参数:" + jsonStr);
            return new CommonResult().success(packageParams);
        }catch (Exception e){
            e.printStackTrace();
            return new CommonResult().failed(e.getMessage());
        }

    }

    /**
     * 企业付款到零钱
     */
    @RequestMapping(value = "/transfer", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String transfer(HttpServletRequest request, @RequestParam("openId") String openId) {

        String ip = IpKit.getRealIp(request);
        if (StrKit.isBlank(ip)) {
            ip = "127.0.0.1";
        }

        WxPayApiConfig wxPayApiConfig = this.getApiConfig();

        Map<String, String> params = TransferModel.builder()
                .mch_appid(wxPayApiConfig.getAppId())
                .mchid(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .partner_trade_no(WxPayKit.generateStr())
                .openid(openId)
                .check_name("NO_CHECK")
                .amount("100")
                .desc("mallplus Pay 让支付触手可及-企业付款")
                .spbill_create_ip(ip)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256, false);

        // 提现
        String transfers = WxPayApi.transfers(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        log.info("提现结果:" + transfers);
        Map<String, String> map = WxPayKit.xmlToMap(transfers);
        String returnCode = map.get("return_code");
        String resultCode = map.get("result_code");
        if (WxPayKit.codeIsOk(returnCode) && WxPayKit.codeIsOk(resultCode)) {
            // 提现成功
        } else {
            // 提现失败
        }
        return transfers;
    }

    /**
     * 查询企业付款到零钱
     */
    @RequestMapping(value = "/transferInfo", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String transferInfo(@RequestParam("partner_trade_no") String partnerTradeNo) {
        try {
            WxPayApiConfig wxPayApiConfig = this.getApiConfig();

            Map<String, String> params = GetTransferInfoModel.builder()
                    .nonce_str(WxPayKit.generateStr())
                    .partner_trade_no(partnerTradeNo)
                    .mch_id(wxPayApiConfig.getMchId())
                    .appid(wxPayApiConfig.getAppId())
                    .build()
                    .createSign(wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256, false);

            return WxPayApi.getTransferInfo(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取RSA加密公钥
     */
    @RequestMapping(value = "/getPublicKey", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String getPublicKey() {
        try {
            WxPayApiConfig wxPayApiConfig = this.getApiConfig();

            Map<String, String> params = new HashMap<String, String>(4);
            params.put("mch_id", wxPayApiConfig.getMchId());
            params.put("nonce_str", String.valueOf(System.currentTimeMillis()));
            params.put("sign_type", "MD5");
            String createSign = WxPayKit.createSign(params, wxPayApiConfig.getPartnerKey(), SignType.MD5);
            params.put("sign", createSign);
            return WxPayApi.getPublicKey(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 企业付款到银行卡
     */
    @RequestMapping(value = "/payBank", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String payBank() {
        try {
            WxPayApiConfig wxPayApiConfig = this.getApiConfig();

            //通过WxPayApi.getPublicKey接口获取RSA加密公钥
            //假设获取到的RSA加密公钥为PUBLIC_KEY(PKCS#8格式)
            final String PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6Bl76IwSvBTiibZ+CNRUA6BfahMshZ0WJpHD1GpmvcQjeN6Yrv6c9eIl6gB4nU3isN7bn+LmoVTpH1gHViaV2YyG/zXj4z4h7r+V+ezesMqqorEg38BCNUHNmhnw4/C0I4gBAQ4x0SJOGnfKGZKR9yzvbkJtvEn732JcEZCbdTZmaxkwlenXvM+mStcJaxBCB/h5xJ5VOF5nDbTPzLphIpzddr3zx/Jxjna9QB1v/YSKYXn+iuwruNUXGCvvxBWaBGKrjOdRTRy9adWOgNmtuYDQJ2YOfG8PtPe06ELKjmr2CfaAGrKKUroyaGvy3qxAV0PlT+UQ4ADSXWt/zl0o5wIDAQAB";

            Map<String, String> params = new HashMap<String, String>(10);
            params.put("mch_id", wxPayApiConfig.getMchId());
            params.put("partner_trade_no", System.currentTimeMillis() + "");
            params.put("nonce_str", System.currentTimeMillis() + "");
            //收款方银行卡号
            params.put("enc_bank_no", RsaKit.encryptByPublicKeyByWx("银行卡号", PUBLIC_KEY));
            //收款方用户名
            params.put("enc_true_name", RsaKit.encryptByPublicKeyByWx("银行卡持有人姓名", PUBLIC_KEY));
            //收款方开户行
            params.put("bank_code", "1001");
            params.put("amount", "1");
            params.put("desc", "mallplus Pay 让支付触手可及-付款到银行卡");
            params.put("sign", WxPayKit.createSign(params, wxPayApiConfig.getPartnerKey(), SignType.HMACSHA256));
            return WxPayApi.payBank(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询企业付款到银行
     */
    @RequestMapping(value = "/queryBank", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String queryBank(@RequestParam("partner_trade_no") String partnerTradeNo) {
        try {
            WxPayApiConfig wxPayApiConfig = this.getApiConfig();

            Map<String, String> params = new HashMap<String, String>(4);
            params.put("mch_id", wxPayApiConfig.getMchId());
            params.put("partner_trade_no", partnerTradeNo);
            params.put("nonce_str", System.currentTimeMillis() + "");
            params.put("sign", WxPayKit.createSign(params, wxPayApiConfig.getPartnerKey(), SignType.MD5));
            return WxPayApi.queryBank(params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 微信退款
     */
    @RequestMapping(value = "/refund", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String refund(@RequestParam("transactionId") String transactionId,
                         @RequestParam("out_trade_no") String outTradeNo) {

        if (StrKit.isBlank(outTradeNo) && StrKit.isBlank(transactionId)) {
            return "transactionId、out_trade_no二选一";
        }
        WxPayApiConfig wxPayApiConfig = this.getApiConfig();

        Map<String, String> params = RefundModel.builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .transaction_id(transactionId)
                .out_trade_no(outTradeNo)
                .out_refund_no(WxPayKit.generateStr())
                .total_fee("1")
                .refund_fee("1")
                .notify_url(refundNotifyUrl)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);

        return WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
    }

    /**
     * 微信退款查询
     */
    @RequestMapping(value = "/refundQuery", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String refundQuery(@RequestParam("transactionId") String transactionId,
                              @RequestParam("out_trade_no") String outTradeNo,
                              @RequestParam("out_refund_no") String outRefundNo,
                              @RequestParam("refund_id") String refundId) {

        WxPayApiConfig wxPayApiConfig = this.getApiConfig();

        Map<String, String> params = RefundQueryModel.builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .transaction_id(transactionId)
                .out_trade_no(outTradeNo)
                .out_refund_no(outRefundNo)
                .refund_id(refundId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);

        return WxPayApi.orderRefundQuery(false, params);
    }

    /**
     * 退款通知
     */
    @RequestMapping(value = "/refundNotify", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String refundNotify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);
        log.info("微信退款通知=" + xmlMsg);
        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);

        String returnCode = params.get("return_code");
        // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态
        if (WxPayKit.codeIsOk(returnCode)) {
            String reqInfo = params.get("req_info");
            String decryptData = WxPayKit.decryptData(reqInfo, this.getApiConfig().getPartnerKey());
            log.info("退款通知解密后的数据=" + decryptData);
            // 更新订单信息
            // 发送通知等
            Map<String, String> xml = new HashMap<String, String>(2);
            xml.put("return_code", "SUCCESS");
            xml.put("return_msg", "OK");
            return WxPayKit.toXml(xml);
        }
        return null;
    }

    /**
     * 异步通知
     */
    @RequestMapping(value = "/payNotify", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String payNotify(HttpServletRequest request) {
        String xmlMsg = HttpKit.readData(request);

        Map<String, String> params = WxPayKit.xmlToMap(xmlMsg);
        log.info("微信支付通知=" + params);
        String returnCode = params.get("return_code");
        //订单编号
        String out_trade_no = params.get("out_trade_no");
        OmsOrder param = new OmsOrder();
        param.setOrderSn(out_trade_no);
        List<OmsOrder> list = orderService.list(new QueryWrapper<>(param));
        OmsOrder orderInfo = list.get(0);
        orderInfo.setStatus(OrderStatus.TO_DELIVER.getValue());
        orderInfo.setPaymentTime(new Date());
        // 注意重复通知的情况,同一订单号可能收到多次通知,请注意一定先判断订单状态
        // 注意此处签名方式需与统一下单的签名类型一致
        if (WxPayKit.verifyNotify(params, this.getApiConfig().getPartnerKey(), SignType.HMACSHA256)) {
            if (WxPayKit.codeIsOk(returnCode)) {
                // 更新订单信息
                orderService.updateById(orderInfo);
                // 发送通知等
                Map<String, String> xml = new HashMap<String, String>(2);
                xml.put("return_code", "SUCCESS");
                xml.put("return_msg", "OK");
                return WxPayKit.toXml(xml);
            }else {
                log.error("订单" + out_trade_no + "支付失败");
                orderService.releaseStock(orderInfo);
            }
        }
        return null;
    }
}

2.支持各种方式的支付宝支付接口

package com.zscat.mallplus.pay.controller.alipay;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.domain.*;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.response.AlipayTradeCreateResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.zscat.mallplus.alipay.AliPayApi;
import com.zscat.mallplus.alipay.AliPayApiConfig;
import com.zscat.mallplus.alipay.AliPayApiConfigKit;
import com.zscat.mallplus.alipay.AliPayBean;
import com.zscat.mallplus.core.kit.PayKit;
import com.zscat.mallplus.core.kit.RsaKit;
import com.zscat.mallplus.enums.OrderStatus;
import com.zscat.mallplus.exception.ApiMallPlusException;
import com.zscat.mallplus.oms.entity.OmsOrder;
import com.zscat.mallplus.oms.entity.OmsPayments;
import com.zscat.mallplus.oms.service.IOmsOrderItemService;
import com.zscat.mallplus.oms.service.IOmsOrderService;
import com.zscat.mallplus.oms.service.IOmsPaymentsService;
import com.zscat.mallplus.pay.utils.StringUtils;
import com.zscat.mallplus.ums.service.IUmsMemberService;
import com.zscat.mallplus.util.JsonUtils;
import com.zscat.mallplus.utils.CommonResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>mallplus Pay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
 *
 * <p>不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。 </p>
 *
 * <p>mallplus Pay 交流群: 320860169</p>
 *
 * <p>Node.js 版: https://gitee.com/javen205/TNW</p>
 *
 * <p>支付宝支付 Demo</p>
 *
 * @author Javen
 */
@RestController
@RequestMapping("/api/aliPay")
public class AliPayController extends AbstractAliPayApiController {
    private static final Logger log = LoggerFactory.getLogger(AliPayController.class);
    String domain = "";
    String privateKey = "";
    String publicKey = "";
    String appId = "";
    @Resource
    private IOmsOrderService orderService;
    @Resource
    private IUmsMemberService memberService;
    @Resource
    private IOmsOrderItemService orderItemService;

    @Autowired
    private IOmsPaymentsService paymentsService;


    @Override
    public AliPayApiConfig getApiConfig() {
        AliPayApiConfig aliPayApiConfig = null;
        try {
            //aliPayApiConfig = AliPayApiConfigKit.getApiConfig(aliPayBean.getAppId());
            OmsPayments payments = paymentsService.getById(2);
            if (payments != null) {
                AliPayBean aliPayBean = JsonUtils.jsonToPojo(payments.getParams(), AliPayBean.class);
                aliPayApiConfig = AliPayApiConfig.builder()
                        .setAppId(aliPayBean.getAppId())
                        .setAliPayPublicKey(aliPayBean.getPublicKey())
                        .setCharset("UTF-8")
                        .setPrivateKey(aliPayBean.getPrivateKey())
                        .setServiceUrl(aliPayBean.getServerUrl())
                        .setSignType("RSA2")
                        .build();
                domain = aliPayBean.getDomain();
                privateKey = aliPayBean.getPrivateKey();
                publicKey = aliPayBean.getPublicKey();
                appId = aliPayBean.getAppId();
            }

        } catch (Exception e) {
            AliPayBean aliPayBean = new AliPayBean();
            aliPayBean.setAppId("2017010804923732");
            aliPayBean.setDomain("http://www.yjlive.cn/api/api");
            aliPayBean.setServerUrl("https://openapi.alipay.com/gateway.do");
            aliPayBean.setPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzQsSWsgXJO7HTWLd/8Y9de6kPBlGqvnBCdL6N8pbg9TZ5LDQOpPxef940nY/dHQiBw61bVZQULSps2mhOs7xjebhEJfhXiGV+aZBjacxr+qJ4EpM/pjH3MrfA8IB5MpB9OFEeOTGos3FMzeQHPiqeeDAIDEFs4fO112/3OWfCD6rLI88H0FoDqZ4oSsAkniFZAW1IjwW9Whgicgo4v3IjcWV+k4eFCSCORpnNKjLbsco0qJic1FaHqbkccnpW8/40j/Vo/ZZG/qCDyZ/Lt7+OKDgO8dzelFfG/IoAuEMGsgb26tCAZMVyjMxXUgLrqnTESAx6121pqy1fiwyMC6cRwIDAQAB\n");
            aliPayBean.setPrivateKey("MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDNCxJayBck7sdNYt3/xj117qQ8GUaq+cEJ0vo3yluD1NnksNA6k/F5/3jSdj90dCIHDrVtVlBQtKmzaaE6zvGN5uEQl+FeIZX5pkGNpzGv6ongSkz+mMfcyt8DwgHkykH04UR45MaizcUzN5Ac+Kp54MAgMQWzh87XXb/c5Z8IPqssjzwfQWgOpnihKwCSeIVkBbUiPBb1aGCJyCji/ciNxZX6Th4UJII5Gmc0qMtuxyjSomJzUVoepuRxyelbz/jSP9Wj9lkb+oIPJn8u3v44oOA7x3N6UV8b8igC4QwayBvbq0IBkxXKMzFdSAuuqdMRIDHrXbWmrLV+LDIwLpxHAgMBAAECggEACYIM7NbAc/76kPUXtEeeC/zv8rV9WGpScEEvRy0EB130aK1mSoEXvn+BO8kt8hl8hnVBJnvNJ6DpCZ/JUS/NdbYSE7HnSnUmPjhea9In9K9ci2EGpvuwsOVbaBI0Akb6vf9ALJb3Ow9tqI1YCm/hf9tTLWr4h7Wxer0nK3geYsRn6O92AKFYjxvImR/qj9sr2DNHg83lX/2YkdDuxhLWF8oTZzunhqvEWo17mEcCrFpx/vY3bME+ZMG/IAtp89PFXXsNHii4nI0buR8mx4z6CgIetgL0qFJUeMUir1ZKn+uAyy9Jv1V9Bu7R07LXsjlZlA/xnew5ie/42iyGcusYiQKBgQDvRiPWCX0eEe4rVcPHAZJ1d/jsOGwvhzmE4TUQdnjVU0bKdgY4hHS9BrvjCTAWmzEE0siS85inzQj26DGGNr5U+D0HYfTEymNQNBMLin/ApLvNPL7xzFdpA19sVvatVV+c5Vl9JaVGuBraK69Q7Cz/6OQwXU1NGQWohZhOyMX6MwKBgQDbYF2BM7npaXFQVbigGmXgdvLHeWdZag7M4dB0lHsqGWAdtQzIIn05q9rBWNMusEfal/eZKuvmoXaDquh/g0VDCmmxxIE4OS9j37g64/4QbWJxwM8rDzA6Z58peng7CUse9Pb3Q/F8JQ/EvniEa6JT1qXWGWhQcpGsACCZEYYpnQKBgGQPAsFo6md+vAhnLx2zbJmu9+tglO0zMTx+KQCfalxbHMlhnaxYx7Ccdkm09+UcNN19f97j+zyAo3UNGFi139YMkQjbT85TjEBn5mb3HgFjYh2rf3YCK7OAc5EMtM87WmZ0Cn4pFfqC1sfRaNkASrkhnPsUqVTKV/FnHJAlqZS9AoGBAJgAKCmajolEzwerrXX5dHdX05YU72AL1V9uY0IzkzczR96tkMKm6v9nrPXktsaVy+ORAjS1gahWXciTRe78JKRz9ZH/ps0vCj/4Ri0/xczaDajlwGWEa5U8MRLLUb0ODmfPscLX591tzIQ0uUp/TYUrp9I13opHJ9n2aJ/GfaAdAoGARUzil6jIO3mASNaH7MPR4MqvxMO0LuBwaVxR1mvM7GtDDDYWU3fTJ6lFpyr340cYgEmHAVnLezbLmP75Jqo42j7H5V3BplPITSSik9ti3WOHFlPRYsZBewL7cJb4VX5oRrbfOX8to9wfw2TvofHE82NDtQn9fQUoFpqKlkIraL4=\n");
            aliPayApiConfig = AliPayApiConfig.builder()
                    .setAppId(aliPayBean.getAppId())
                    .setAliPayPublicKey(aliPayBean.getPublicKey())
                    .setCharset("UTF-8")
                    .setPrivateKey(aliPayBean.getPrivateKey())
                    .setServiceUrl(aliPayBean.getServerUrl())
                    .setSignType("RSA2")
                    .build();
            domain = aliPayBean.getDomain();
            privateKey = aliPayBean.getPrivateKey();
            publicKey = aliPayBean.getPublicKey();
            appId = aliPayBean.getAppId();
        }
        return aliPayApiConfig;

    }

    @RequestMapping("")
    @ResponseBody
    public String index() {
        return "欢迎使用 mallplus Pay 中的支付宝支付 -By Javen  <br/><br>  交流群:320860169";
    }

    @RequestMapping("/test")
    @ResponseBody
    public AliPayApiConfig test() {
        AliPayApiConfig aliPayApiConfig = AliPayApiConfigKit.getAliPayApiConfig();
        String charset = aliPayApiConfig.getCharset();
        log.info("charset>" + charset);
        return aliPayApiConfig;
    }


    /**
     * app支付
     */
    @RequestMapping(value = "/appPay")
    @ResponseBody
    public Object appPay(@RequestParam(value = "orderId", required = false, defaultValue = "0") Long orderId) {
        try {

            OmsOrder orderInfo = orderService.getById(orderId);
            if (null == orderInfo) {
                return new CommonResult().failed("订单已取消" );
            }
            if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
                return new CommonResult().failed( "订单已已关闭,请不要重复操作" );
            }
            if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
                return new CommonResult().failed( "订单已支付,请不要重复操作" );
            }

            AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
            model.setBody("zhifu");
            model.setSubject("mallplus app支付");
            model.setOutTradeNo(orderInfo.getOrderSn());
            model.setTimeoutExpress("30m");
            model.setTotalAmount(orderInfo.getPayAmount().floatValue()+"");
            model.setPassbackParams("callback params");
            model.setProductCode("QUICK_MSECURITY_PAY");
            String order = AliPayApi.appPayToResponse(model, domain + "/aliPay/notify_url",this.getApiConfig()).getBody();
            System.out.println(JSONObject.toJSONString(orderInfo));
            return new CommonResult().success(order);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return new CommonResult().failed(e.getMessage());
        }
    }

    @RequestMapping(value = "/wapPayNoSdk")
    @ResponseBody
    public void wapPayNoSdk(HttpServletResponse response,@RequestParam(value = "orderId", required = false, defaultValue = "0") Long orderId) {
        try {
            OmsOrder orderInfo = orderService.getById(orderId);
            if (null == orderInfo) {
                throw new ApiMallPlusException("订单已取消" );
            }
            if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
                throw new ApiMallPlusException( "订单已已关闭,请不要重复操作" );
            }
            if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
                throw new ApiMallPlusException( "订单已支付,请不要重复操作" );
            }
            AliPayApiConfig aliPayApiConfig = AliPayApiConfigKit.getAliPayApiConfig();
            Map<String, String> paramsMap = new HashMap<>();
            paramsMap.put("app_id", aliPayApiConfig.getAppId());
            paramsMap.put("method", "alipay.trade.wap.pay");
            paramsMap.put("return_url", domain + "aliPay/return_url");
            paramsMap.put("charset", aliPayApiConfig.getCharset());
            paramsMap.put("sign_type", aliPayApiConfig.getSignType());
            paramsMap.put("timestamp", DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss"));
            paramsMap.put("version", "1.0");
            paramsMap.put("notify_url", domain + "/aliPay/notify_url");

            Map<String, String> bizMap = new HashMap<>();
            bizMap.put("body", "mallplus 聚合支付-H5");
            bizMap.put("subject", "mallplus Pay 让支付触手可及");
            bizMap.put("out_trade_no", StringUtils.getOutTradeNo());
            bizMap.put("total_amount", orderInfo.getPayAmount().toString());
            bizMap.put("product_code", "QUICK_WAP_WAY");

            paramsMap.put("biz_content", JSON.toJSONString(bizMap));

            String content = PayKit.createLinkString(paramsMap);

            System.out.println(content);

            String encrypt = RsaKit.encryptByPrivateKey(content, aliPayApiConfig.getPrivateKey());
//            encrypt = AlipaySignature.rsaSign(content,aliPayApiConfig.getPrivateKey(), "UTF-8","RSA2");
//            System.out.println(encrypt);
            paramsMap.put("sign", encrypt);

            String url = aliPayApiConfig.getServiceUrl() + "?" + PayKit.createLinkString(paramsMap, true);
            System.out.println(url);
            response.sendRedirect(url);

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

    @RequestMapping(value = "/wapPay")
    @ResponseBody
    public Object wapPay(HttpServletResponse response,@RequestParam(value = "orderId", required = true, defaultValue = "0") Long orderId) {
        OmsOrder orderInfo = orderService.getById(orderId);
        if (null == orderInfo) {
            return new CommonResult().failed("订单已取消" );
        }
        if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
            return new CommonResult().failed( "订单已已关闭,请不要重复操作" );
        }
        if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
            return new CommonResult().failed( "订单已支付,请不要重复操作" );
        }

        String body = orderInfo.getGoodsName();
        String subject = "mallplus支付测试";
        String passbackParams = "1";
        String returnUrl = domain + "/aliPay/return_url";
        String notifyUrl = domain + "/aliPay/notify_url";

        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setBody(subject);
        model.setSubject(subject);
        model.setTotalAmount(orderInfo.getPayAmount().floatValue()+"");
        model.setPassbackParams(passbackParams);
        model.setOutTradeNo(orderInfo.getOrderSn());
        model.setProductCode(orderInfo.getOrderSn());

        try {
            return new CommonResult().success(AliPayApi.wapPayStr( model, returnUrl, notifyUrl,this.getApiConfig()));
        } catch (Exception e) {
            e.printStackTrace();
            return new CommonResult().failed(e.getMessage());
        }

    }


    /**
     * PC支付
     */
    @RequestMapping(value = "/pcPay")
    @ResponseBody
    public void pcPay(HttpServletResponse response ,@RequestParam(value = "orderId", required = true, defaultValue = "0") Long orderId) {
        try {
            OmsOrder orderInfo = orderService.getById(orderId);
            if (null == orderInfo) {
                throw new ApiMallPlusException("订单已取消" );
            }
            if (orderInfo.getStatus() == OrderStatus.CLOSED.getValue()) {
                throw new ApiMallPlusException( "订单已已关闭,请不要重复操作" );
            }
            if (orderInfo.getStatus() != OrderStatus.INIT.getValue()) {
                throw new ApiMallPlusException( "订单已支付,请不要重复操作" );
            }
            String returnUrl = domain + "/aliPay/return_url";
            String notifyUrl = domain + "/aliPay/notify_url";
            AlipayTradePagePayModel model = new AlipayTradePagePayModel();

            model.setOutTradeNo(orderInfo.getOrderSn());
            model.setProductCode("FAST_INSTANT_TRADE_PAY");
            model.setTotalAmount(orderInfo.getPayAmount().floatValue()+"");
            model.setSubject("Javen PC支付测试");
            model.setBody("Javen mallplus Pay PC支付测试");
            model.setPassbackParams("passback_params");
            /**
             * 花呗分期相关的设置,测试环境不支持花呗分期的测试
             * hb_fq_num代表花呗分期数,仅支持传入3、6、12,其他期数暂不支持,传入会报错;
             * hb_fq_seller_percent代表卖家承担收费比例,商家承担手续费传入100,用户承担手续费传入0,仅支持传入100、0两种,其他比例暂不支持,传入会报错。
             */
            ExtendParams extendParams = new ExtendParams();
            extendParams.setHbFqNum("3");
            extendParams.setHbFqSellerPercent("0");
            model.setExtendParams(extendParams);

            AliPayApi.tradePage(response, model, notifyUrl, returnUrl,this.getApiConfig());
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 统一收单交易支付接口接口
     *
     * @param authCode
     * @param scene
     * @return
     */
    @RequestMapping(value = "/tradePay")
    @ResponseBody
    public Object tradePay(@RequestParam("auth_code") String authCode, @RequestParam("scene") String scene) {
        String subject = null;
        String waveCode = "wave_code";
        String barCode = "bar_code";
        if (scene.equals(waveCode)) {
            subject = "Javen 支付宝声波支付测试";
        } else if (scene.equals(barCode)) {
            subject = "Javen 支付宝条形码支付测试";
        }
        String totalAmount = "100";
        String notifyUrl = domain + "/aliPay/notify_url";

        AlipayTradePayModel model = new AlipayTradePayModel();
        model.setAuthCode(authCode);
        model.setSubject(subject);
        model.setTotalAmount(totalAmount);
        model.setOutTradeNo(StringUtils.getOutTradeNo());
        model.setScene(scene);
        try {
            return new CommonResult().success(AliPayApi.tradePayToResponse(model, notifyUrl,this.getApiConfig()).getBody());
        } catch (Exception e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 扫码支付
     */
    @RequestMapping(value = "/tradePrecreatePay")
    @ResponseBody
    public String tradePrecreatePay() {
        String subject = "Javen 支付宝扫码支付测试";
        String totalAmount = "86";
        String storeId = "123";
        String notifyUrl = domain + "/aliPay/notify_url";

        AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
        model.setSubject(subject);
        model.setTotalAmount(totalAmount);
        model.setStoreId(storeId);
        model.setTimeoutExpress("5m");
        model.setOutTradeNo(StringUtils.getOutTradeNo());
        try {
            String resultStr = AliPayApi.tradePrecreatePayToResponse(model, notifyUrl,this.getApiConfig()).getBody();
            JSONObject jsonObject = JSONObject.parseObject(resultStr);
            return jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 单笔转账到支付宝账户
     * https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.54Ty29&
     * treeId=193&articleId=106236&docType=1
     */
    @RequestMapping(value = "/transfer")
    @ResponseBody
    public boolean transfer() {
        boolean isSuccess = false;
        String totalAmount = "66";
        AlipayFundTransToaccountTransferModel model = new AlipayFundTransToaccountTransferModel();
        model.setOutBizNo(StringUtils.getOutTradeNo());
        model.setPayeeType("ALIPAY_LOGONID");
        model.setPayeeAccount("[email protected]");
        model.setAmount(totalAmount);
        model.setPayerShowName("测试退款");
        model.setPayerRealName("沙箱环境");
        model.setRemark("javen测试单笔转账到支付宝");

        try {
            isSuccess = AliPayApi.transfer(model,this.getApiConfig());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isSuccess;
    }

    /**
     * 资金授权冻结接口
     */
    @RequestMapping(value = "/authOrderFreeze")
    @ResponseBody
    public Object authOrderFreeze(@RequestParam("auth_code") String authCode) {
        try {
            AlipayFundAuthOrderFreezeModel model = new AlipayFundAuthOrderFreezeModel();
            model.setOutOrderNo(StringUtils.getOutTradeNo());
            model.setOutRequestNo(StringUtils.getOutTradeNo());
            model.setAuthCode(authCode);
            model.setAuthCodeType("bar_code");
            model.setOrderTitle("资金授权冻结-By mallplus Pay");
            model.setAmount("36");
            model.setProductCode("PRE_AUTH");

            return new CommonResult().success(AliPayApi.authOrderFreezeToResponse(model,this.getApiConfig()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * 红包协议支付接口
     * https://docs.open.alipay.com/301/106168/
     */
    @RequestMapping(value = "/agreementPay")
    @ResponseBody
    public Object agreementPay() {
        try {
            AlipayFundCouponOrderAgreementPayModel model = new AlipayFundCouponOrderAgreementPayModel();
            model.setOutOrderNo(StringUtils.getOutTradeNo());
            model.setOutRequestNo(StringUtils.getOutTradeNo());
            model.setOrderTitle("红包协议支付接口-By mallplus Pay");
            model.setAmount("36");
            model.setPayerUserId("2088102180432465");

            return new CommonResult().success(AliPayApi.fundCouponOrderAgreementPayToResponse(model,this.getApiConfig()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 下载对账单
     */
    @RequestMapping(value = "/dataDataserviceBill")
    @ResponseBody
    public Object dataDataserviceBill(@RequestParam("billDate") String billDate) {
        try {
            AlipayDataDataserviceBillDownloadurlQueryModel model = new AlipayDataDataserviceBillDownloadurlQueryModel();
            model.setBillType("trade");
            model.setBillDate(billDate);
            return new CommonResult().success(AliPayApi.billDownloadurlQuery(model,this.getApiConfig()));
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 退款
     */
    @RequestMapping(value = "/tradeRefund")
    @ResponseBody
    public Object tradeRefund() {

        try {
            AlipayTradeRefundModel model = new AlipayTradeRefundModel();
            model.setOutTradeNo("081014283315023");
            model.setTradeNo("2017081021001004200200273870");
            model.setRefundAmount("86.00");
            model.setRefundReason("正常退款");
            return new CommonResult().success(AliPayApi.tradeRefundToResponse(model,this.getApiConfig()).getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 交易查询
     */
    @RequestMapping(value = "/tradeQuery")
    @ResponseBody
    public boolean tradeQuery() {
        boolean isSuccess = false;
        try {
            AlipayTradeQueryModel model = new AlipayTradeQueryModel();
            model.setOutTradeNo("081014283315023");
            model.setTradeNo("2017081021001004200200273870");

            isSuccess = AliPayApi.tradeQueryToResponse(model,this.getApiConfig()).isSuccess();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return isSuccess;
    }

    @RequestMapping(value = "/tradeQueryByStr")
    @ResponseBody
    public Object tradeQueryByStr(@RequestParam("out_trade_no") String outTradeNo) {
        AlipayTradeQueryModel model = new AlipayTradeQueryModel();
        model.setOutTradeNo(outTradeNo);

        try {
            return new CommonResult().success(AliPayApi.tradeQueryToResponse(model,this.getApiConfig()).getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }

        return null;
    }

    /**
     * 创建订单
     * {"alipay_trade_create_response":{"code":"10000","msg":"Success","out_trade_no":"081014283315033","trade_no":"2017081021001004200200274066"},"sign":"ZagfFZntf0loojZzdrBNnHhenhyRrsXwHLBNt1Z/dBbx7cF1o7SZQrzNjRHHmVypHKuCmYifikZIqbNNrFJauSuhT4MQkBJE+YGPDtHqDf4Ajdsv3JEyAM3TR/Xm5gUOpzCY7w+RZzkHevsTd4cjKeGM54GBh0hQH/gSyhs4pEN3lRWopqcKkrkOGZPcmunkbrUAF7+AhKGUpK+AqDw4xmKFuVChDKaRdnhM6/yVsezJFXzlQeVgFjbfiWqULxBXq1gqicntyUxvRygKA+5zDTqE5Jj3XRDjVFIDBeOBAnM+u03fUP489wV5V5apyI449RWeybLg08Wo+jUmeOuXOA=="}
     */
    @RequestMapping(value = "/tradeCreate")
    @ResponseBody
    public Object tradeCreate(@RequestParam("out_trade_no") String outTradeNo) {

        String notifyUrl = domain + "/aliPay/notify_url";

        AlipayTradeCreateModel model = new AlipayTradeCreateModel();
        model.setOutTradeNo(outTradeNo);
        model.setTotalAmount("88.88");
        model.setBody("Body");
        model.setSubject("Javen 测试统一收单交易创建接口");
        //买家支付宝账号,和buyer_id不能同时为空
        model.setBuyerLogonId("[email protected]");
        try {
            AlipayTradeCreateResponse response = AliPayApi.tradeCreateToResponse(model, notifyUrl,this.getApiConfig());
            return new CommonResult().success(response.getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 撤销订单
     */
    @RequestMapping(value = "/tradeCancel")
    @ResponseBody
    public Object tradeCancel() {
        boolean isSuccess = false;
        try {
            AlipayTradeCancelModel model = new AlipayTradeCancelModel();
            model.setOutTradeNo("081014283315033");
            model.setTradeNo("2017081021001004200200274066");

            isSuccess = AliPayApi.tradeCancelToResponse(model,this.getApiConfig()).isSuccess();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return new CommonResult().success(isSuccess);
    }

    /**
     * 关闭订单
     */
    @RequestMapping(value = "/tradeClose")
    @ResponseBody
    public Object tradeClose(@RequestParam("out_trade_no") String outTradeNo, @RequestParam("trade_no") String tradeNo) {
        try {
            AlipayTradeCloseModel model = new AlipayTradeCloseModel();
            model.setOutTradeNo(outTradeNo);

            model.setTradeNo(tradeNo);

            return new CommonResult().success(AliPayApi.tradeCloseToResponse(model,this.getApiConfig()).getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 结算
     */
    @RequestMapping(value = "/tradeOrderSettle")
    @ResponseBody
    public Object tradeOrderSettle(@RequestParam("trade_no") String tradeNo) {
        try {
            AlipayTradeOrderSettleModel model = new AlipayTradeOrderSettleModel();
            model.setOutRequestNo(StringUtils.getOutTradeNo());
            model.setTradeNo(tradeNo);

            return new CommonResult().success(AliPayApi.tradeOrderSettleToResponse(model,this.getApiConfig()).getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取应用授权URL并授权
     */
    @RequestMapping(value = "/toOauth")
    @ResponseBody
    public void toOauth(HttpServletResponse response) {
        try {
            String redirectUri = domain + "/aliPay/redirect_uri";
            String oauth2Url = AliPayApi.getOauth2Url(appId, redirectUri);
            response.sendRedirect(oauth2Url);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 应用授权回调
     */
    @RequestMapping(value = "/redirect_uri")
    @ResponseBody
    public Object redirectUri(@RequestParam("app_id") String appId, @RequestParam("app_auth_code") String appAuthCode) {
        try {
            System.out.println("app_id:" + appId);
            System.out.println("app_auth_code:" + appAuthCode);
            //使用app_auth_code换取app_auth_token
            AlipayOpenAuthTokenAppModel model = new AlipayOpenAuthTokenAppModel();
            model.setGrantType("authorization_code");
            model.setCode(appAuthCode);
            return new CommonResult().success(AliPayApi.openAuthTokenAppToResponse(model,this.getApiConfig()).getBody());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询授权信息
     */
    @RequestMapping(value = "/openAuthTokenAppQuery")
    @ResponseBody
    public Object openAuthTokenAppQuery(@RequestParam("app_auth_token") String appAuthToken) {
        try {
            AlipayOpenAuthTokenAppQueryModel model = new AlipayOpenAuthTokenAppQueryModel();
            model.setAppAuthToken(appAuthToken);
            return new CommonResult().success(AliPayApi.openAuthTokenAppQueryToResponse(model,this.getApiConfig()).getBody());
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 批量付款到支付宝账户有密接口
     */
    @RequestMapping(value = "/batchTrans")
    @ResponseBody
    public void batchTrans(HttpServletResponse response) {
        try {
            String signType = "MD5";
            String notifyUrl = domain + "/aliPay/notify_url";
            Map<String, String> params = new HashMap<>(15);
            params.put("partner", "PID");
            params.put("sign_type", signType);
            params.put("notify_url", notifyUrl);
            params.put("account_name", "xxx");
            params.put("detail_data", "流水号1^收款方账号1^收款账号姓名1^付款金额1^备注说明1|流水号2^收款方账号2^收款账号姓名2^付款金额2^备注说明2");
            params.put("batch_no", String.valueOf(System.currentTimeMillis()));
            params.put("batch_num", 1 + "");
            params.put("batch_fee", 10.00 + "");
            params.put("email", "[email protected]");

            AliPayApi.batchTrans(params, privateKey, signType, response);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 地铁购票核销码发码
     */
    @RequestMapping(value = "/voucherGenerate")
    @ResponseBody
    public String voucherGenerate(@RequestParam("tradeNo") String tradeNo) {
        try {
            //需要支付成功的订单号
//			String tradeNo = getPara("tradeNo");

            AlipayCommerceCityfacilitatorVoucherGenerateModel model = new AlipayCommerceCityfacilitatorVoucherGenerateModel();
            model.setCityCode("440300");
            model.setTradeNo(tradeNo);
            model.setTotalFee("8");
            model.setTicketNum("2");
            model.setTicketType("oneway");
            model.setSiteBegin("001");
            model.setSiteEnd("002");
            model.setTicketPrice("4");
            return AliPayApi.voucherGenerateToResponse(model,this.getApiConfig()).getBody();
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    @RequestMapping(value = "/return_url")
    @ResponseBody
    public Object returnUrl(HttpServletRequest request) {
        try {
            // 获取支付宝GET过来反馈信息
            Map<String, String> map = AliPayApi.toMap(request);
            System.out.println("return_url");
            System.out.println(map.toString());
            for (Map.Entry<String, String> entry : map.entrySet()) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }

            boolean verifyResult = AlipaySignature.rsaCheckV1(map, publicKey, "UTF-8",
                    "RSA2");

            if (verifyResult) {
                // TODO 请在这里加上商户的业务逻辑程序代码
                System.out.println("return_url 验证成功");

                return new CommonResult().success();
            } else {
                System.out.println("return_url 验证失败");
                // TODO
                return new CommonResult().failed();
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "failure";
        }
    }


    @RequestMapping(value = "/notify_url")
    @ResponseBody
    public Object notifyUrl(HttpServletRequest request) {
        try {
            // 获取支付宝POST过来反馈信息
            Map<String, String> params = AliPayApi.toMap(request);
            System.out.println("notify_url");
            System.out.println(params.toString());
            for (Map.Entry<String, String> entry : params.entrySet()) {
                System.out.println(entry.getKey() + " = " + entry.getValue());
            }
            String out_trade_no = params.get("out_trade_no");
            OmsOrder param = new OmsOrder();
            param.setOrderSn(out_trade_no);
            List<OmsOrder> list = orderService.list(new QueryWrapper<>(param));
            OmsOrder orderInfo = list.get(0);
            orderInfo.setStatus(OrderStatus.TO_DELIVER.getValue());
            orderInfo.setPaymentTime(new Date());
            boolean verifyResult = AlipaySignature.rsaCheckV1(params, publicKey, "UTF-8", "RSA2");

            if (verifyResult) {
                // 更新订单信息
                orderService.updateById(orderInfo);
                // TODO 请在这里加上商户的业务逻辑程序代码 异步通知可能出现订单重复通知 需要做去重处理
                System.out.println("notify_url 验证成功succcess");
                return new CommonResult().success();
            } else {
                log.error("订单" + out_trade_no + "支付失败");
                orderService.releaseStock(orderInfo);
                // TODO
                return new CommonResult().failed();
            }
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return "failure";
        }
    }
}

3.京东支付 接口

package com.zscat.mallplus.pay.controller.jdpay;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.XmlUtil;
import com.zscat.mallplus.jdpay.JdPayApi;
import com.zscat.mallplus.jdpay.kit.JdPayKit;
import com.zscat.mallplus.jdpay.model.*;
import com.zscat.mallplus.pay.entity.JdPayBean;
import com.zscat.mallplus.pay.vo.AjaxResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.Date;
import java.util.Map;

/**
 * <p>mallplus Pay 让支付触手可及,封装了微信支付、支付宝支付、银联支付常用的支付方式以及各种常用的接口。</p>
 *
 * <p>不依赖任何第三方 mvc 框架,仅仅作为工具使用简单快速完成支付模块的开发,可轻松嵌入到任何系统里。 </p>
 *
 * <p>mallplus Pay 交流群: 320860169</p>
 *
 * <p>Node.js 版: https://gitee.com/javen205/TNW</p>
 *
 * <p>微信支付 Demo</p>
 *
 * @author Javen
 */
@Controller
@RequestMapping("/api/JDPay")
public class JdPayController {
    @Autowired
    JdPayBean jdPayBean;
    private Logger log = LoggerFactory.getLogger(this.getClass());

    @RequestMapping("")
    @ResponseBody
    public String index() {
        log.info("欢迎使用 mallplus Pay 中的京东支付 -By Javen  <br/><br>  交流群:320860169");
        log.info(jdPayBean.toString());
        return ("欢迎使用 mallplus Pay 中的京东支付 -By Javen  <br/><br>  交流群:320860169");
    }

    @GetMapping("/test")
    @ResponseBody
    public JdPayBean test() {
        return jdPayBean;
    }

    /**
     * App 支付
     *
     * @return
     */
    @RequestMapping(value = "/appPay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult appPay() {
        String reqXml = UniOrderModel.builder()
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .tradeNum(System.currentTimeMillis() + "")
                .tradeName("mallplus Pay 让支付触手可及")
                .tradeDesc("https://gitee.com/javen205/mallplus Pay")
                .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))
                .amount("1")
                .orderType("1")
                .currency("CNY")
                .note("备注")
                .notifyUrl("http://jdpaydemo.jd.com/asynNotify.htm")
                .tradeType("GEN")
                .build()
                .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId());

        // 执行请求
        String resultData = JdPayApi.uniOrder(reqXml);

        log.info("resultData:" + resultData);

        // 解析响应的 xml 数据
        Map<String, String> map = JdPayKit.parseResp(resultData);

        String code = map.get("code");
        String encrypt = map.get("encrypt");
        if (!"000000".equals(code)) {
            String desc = map.get("desc");
            return new AjaxResult().addError(desc);
        }
        // 解密并验证签名
        String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt);

        log.info("decrypt>" + decrypt);

        // 将 xml 转化为 map
        Map<String, Object> toMap = XmlUtil.xmlToMap(decrypt);

        log.info("result toMap>" + toMap);


        String orderId = (String) toMap.get("orderId");

        StringBuilder sb = new StringBuilder();
        sb.append("merchant=").append(jdPayBean.getMchId());
        sb.append("&orderId=").append(orderId);
        sb.append("&key=").append("test");
        String sign = JdPayKit.md5LowerCase(sb.toString());

        return new AjaxResult().success(new AppParams(orderId, jdPayBean.getMchId(), "123456789",
                sign, "123456789"));
    }

    /**
     * PC H5 支付
     *
     * @param payType
     * @return
     */
    @RequestMapping(value = "/saveOrder", method = {RequestMethod.POST, RequestMethod.GET})
    public ModelAndView saveOrder(@RequestParam("payType") String payType) {

        ModelAndView mv = new ModelAndView();

        Map<String, String> map = SaveOrderModel.builder()
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .tradeNum(System.currentTimeMillis() + "")
                .tradeName("mallplus Pay")
                .tradeDesc("mallplus Pay 让支付触手可及")
                .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))
                .amount("10000")
                .orderType("0")
                .currency("CNY")
                .note("mallplus Pay 了解一下")
                .callbackUrl("https://jdpay.com")
                .notifyUrl("https://jdpay.com")
                .userId("mallplus Pay001")
                .build()
                .createSign(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey());

        mv.addObject("map", map);
        mv.addObject("payUrl", payType.equals("pc") ? JdPayApi.PC_SAVE_ORDER_URL : JdPayApi.H5_SAVE_ORDER_URL);
        mv.setViewName("jd_pc_h5.html");
        return mv;
    }

    /**
     * 商户二维码支付
     */
    @RequestMapping(value = "/customerPay", method = {RequestMethod.POST, RequestMethod.GET})
    public ModelAndView customerPay() {

        ModelAndView mv = new ModelAndView();

        Map<String, String> map = CustomerPayModel.builder()
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .tradeNum(System.currentTimeMillis() + "")
                .tradeName("mallplus Pay")
                .tradeDesc("mallplus Pay 让支付触手可及")
                .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))
//                .amount("1000")
                .orderType("0")
                .currency("CNY")
                .note("mallplus Pay 了解一下")
                .notifyUrl("https://jdpay.com")
                .build()
                .createSign(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey());

        mv.addObject("map", map);
        mv.addObject("payUrl", JdPayApi.CUSTOMER_PAY_URL);
        mv.setViewName("jd_customer_pay.html");
        return mv;
    }

    @RequestMapping(value = "/queryOrder", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult queryOrder(@RequestParam("tradeType") String tradeType,
                                 @RequestParam("oTradeNum") String oTradeNum,
                                 @RequestParam("tradeNum") String tradeNum) {
        String reqXml = QueryOrderModel.builder()
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .tradeNum(tradeNum)
                .tradeType(tradeType)
                .oTradeNum(oTradeNum)
                .build()
                .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId());
        String queryResult = JdPayApi.queryOrder(reqXml);
        log.info("queryResult:" + queryResult);

        // 解析响应的 xml 数据
        Map<String, String> map = JdPayKit.parseResp(queryResult);

        String code = map.get("code");
        String encrypt = map.get("encrypt");
        if (!"000000".equals(code)) {
            String desc = map.get("desc");
            return new AjaxResult().addError(desc);
        }
        // 解密并验证签名
        String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt);

        log.info("decrypt>" + decrypt);

        return new AjaxResult().success(decrypt);
    }

    @RequestMapping(value = "/fkmPay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult fkmPay(@RequestParam("token") String token,
                             @RequestParam("amount") String amount) {
        String reqXml = FkmModel.builder()
                .token(token)
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .device("mallplus Pay Dev")
                .tradeNum(System.currentTimeMillis() + "")
                .tradeName("mallplus Pay 刷卡支付")
                .tradeDesc("mallplus Pay 了解一下")
                .tradeTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))
                .amount(amount)
                .currency("CNY")
                .note("备注")
                .notifyUrl("https://gitee.com/javen205/mallplus Pay")
                .build()
                .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId());
        String queryResult = JdPayApi.fkmPay(reqXml);
        log.info("queryResult:" + queryResult);

        // 解析响应的 xml 数据
        Map<String, String> map = JdPayKit.parseResp(queryResult);

        String code = map.get("code");
        String encrypt = map.get("encrypt");
        if (!"000000".equals(code)) {
            String desc = map.get("desc");
            return new AjaxResult().addError(desc);
        }
        // 解密并验证签名
        String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt);

        log.info("decrypt>" + decrypt);

        return new AjaxResult().success(decrypt);
    }

    @RequestMapping(value = "/userRelation", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult userRelation(@RequestParam("userId") String userId,
                                   @RequestParam("type") String type) {
        String reqXml = UserRelationModel.builder()
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .userId(userId)
                .build()
                .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId());

        String result = null;

        if ("get".equals(type)) {
            result = JdPayApi.getUserRelation(reqXml);
        } else {
            result = JdPayApi.cancelUserRelation(reqXml);
        }

        log.info(result);

        // 解析响应的 xml 数据
        Map<String, String> map = JdPayKit.parseResp(result);

        String code = map.get("code");
        String encrypt = map.get("encrypt");
        if (!"000000".equals(code)) {
            String desc = map.get("desc");
            return new AjaxResult().addError(desc);
        }
        // 解密并验证签名
        String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt);

        log.info("decrypt>" + decrypt);

        Map<String, Object> toMap = XmlUtil.xmlToMap(decrypt);
        System.out.println(toMap);
        return new AjaxResult().success(decrypt);
    }

    @RequestMapping(value = "/refund", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult refund(@RequestParam("amount") String amount,
                             @RequestParam("oTradeNum") String oTradeNum,
                             @RequestParam("tradeNum") String tradeNum) {

        System.out.println(Base64.encode(FileUtil.readBytes(jdPayBean.getCertPath())));
        String reqXml = RefundModel.builder()
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .tradeNum(tradeNum)
                .oTradeNum(oTradeNum)
                .amount(amount)
                .currency("CNY")
                .build()
                .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId());
        String queryResult = JdPayApi.refund(reqXml);
        log.info("queryResult:" + queryResult);

        // 解析响应的 xml 数据
        Map<String, String> map = JdPayKit.parseResp(queryResult);

        String code = map.get("code");
        String encrypt = map.get("encrypt");
        if (!"000000".equals(code)) {
            String desc = map.get("desc");
            return new AjaxResult().addError(desc);
        }
        // 解密并验证签名
        String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt);

        log.info("decrypt>" + decrypt);

        return new AjaxResult().success(decrypt);
    }


    @RequestMapping(value = "/queryBaiTiaoFq", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult queryBaiTiaoFq(@RequestParam("amount") String amount) {
        String reqXml = QueryBaiTiaoFqModel.builder()
                .version("V2.0")
                .merchant(jdPayBean.getMchId())
                .tradeNum(System.currentTimeMillis() + "")
                .amount(amount)
                .build()
                .genReqXml(jdPayBean.getRsaPrivateKey(), jdPayBean.getDesKey(), "V2.0", jdPayBean.getMchId());

        String baiTiaoResult = JdPayApi.queryBaiTiaoFq(reqXml);

        log.info(baiTiaoResult);

        // 解析响应的 xml 数据
        Map<String, String> map = JdPayKit.parseResp(baiTiaoResult);

        String code = map.get("code");
        String encrypt = map.get("encrypt");
        if (!"000000".equals(code)) {
            String desc = map.get("desc");
            return new AjaxResult().addError(desc);
        }
        // 解密并验证签名
        String decrypt = JdPayKit.decrypt(jdPayBean.getRsaPublicKey(), jdPayBean.getDesKey(), encrypt);

        log.info("decrypt>" + decrypt);

        Map<String, Object> toMap = XmlUtil.xmlToMap(decrypt);
        System.out.println(toMap);
        return new AjaxResult().success(decrypt);
    }
}

4.银联支付

package com.zscat.mallplus.pay.controller.unionpay;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.zscat.mallplus.pay.vo.AjaxResult;
import com.zscat.mallplus.unionpay.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.*;

@Controller
@RequestMapping("/api/unionPay")
public class UnionPayController {
    private static final Logger logger = LoggerFactory.getLogger(UnionPayController.class);

    private AjaxResult ajax = new AjaxResult();

    /**
     * 将回调参数转为Map
     *
     * @param notifyStr
     * @return {Map<String, String>}
     */
    public static Map<String, String> getAllRequestParamToMap(final String notifyStr) {
        Map<String, String> res = new HashMap<String, String>();
        try {
            logger.info("收到通知报文:" + notifyStr);
            String[] kvs = notifyStr.split("&");
            for (String kv : kvs) {
                String[] tmp = kv.split("=");
                if (tmp.length >= 2) {
                    String key = tmp[0];
                    String value = URLDecoder.decode(tmp[1], "UTF-8");
                    res.put(key, value);
                }
            }
        } catch (UnsupportedEncodingException e) {
            logger.info("getAllRequestParamStream.UnsupportedEncodingException error: " + e.getClass() + ":"
                    + e.getMessage());
        }
        return res;
    }

    /**
     * 组装请求,返回报文字符串用于显示
     *
     * @param data
     * @return {String}
     */
    public static String getHtmlResult(Map<String, String> data) {

        TreeMap<String, String> tree = new TreeMap<String, String>();
        Iterator<Map.Entry<String, String>> it = data.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<String, String> en = it.next();
            tree.put(en.getKey(), en.getValue());
        }
        it = tree.entrySet().iterator();
        StringBuffer sf = new StringBuffer();
        while (it.hasNext()) {
            Map.Entry<String, String> en = it.next();
            String key = en.getKey();
            String value = en.getValue();
            if ("respCode".equals(key)) {
                sf.append("<b>" + key + "=" + value + "</br></b>");
            } else
                sf.append(key + "=" + value + "</br>");
        }
        return sf.toString();
    }

    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();
                }
        }
    }

    @RequestMapping("")
    @ResponseBody
    public String index() {
        logger.info("欢迎使用mallplus Pay银联支付	- by Javen");
        return "欢迎使用mallplus Pay银联支付	- by Javen";
    }

    /**
     * PC网关支付
     * B2C跟B2B查询区别就在于bizType的不同
     */
    @RequestMapping(value = "/frontConsume", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void frontConsume(HttpServletResponse response) {
        try {
            Map<String, String> createMap = UnionPayApiConfig.builder()
//					.setChannelType("07") 默认值就是07
                    .setMerId("777290058151764")
                    .setTxnAmt("6666")
                    .setReqReserved("reqReserved")
//					.setFrontUrl(SDKConfig.getConfig().getFrontUrl()) 有默认值
//					.setBackUrl(SDKConfig.getConfig().getBackUrl()) 有默认值
                    .createMap();
            UnionPayApi.frontRequest(response, createMap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * B2B的网关支付 B2C跟B2B查询区别就在于bizType的不同
     */
    @RequestMapping(value = "/frontConsume2", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void frontConsume2(HttpServletResponse response) {
        try {
            Map<String, String> createMap = UnionPayApiConfig.builder()
                    .setBizType("000202")
                    .setChannelType("07")
                    .setMerId("777290058151764")
                    .setTxnAmt("2222")
                    .setReqReserved("reqReserved")
                    .createMap();
            UnionPayApi.frontRequest(response, createMap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * WAP支付 请在手机端访问此action
     */
    @RequestMapping(value = "/wapConsume", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void wapConsume(HttpServletResponse response) {
        try {
            Map<String, String> createMap = UnionPayApiConfig.builder()
                    .setChannelType("08")
                    .setMerId("777290058151764")
                    .setTxnAmt("6868")
                    .setReqReserved("reqReserved")
                    .setFrontUrl(SDKConfig.getConfig().getFrontUrl())
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .createMap();
            UnionPayApi.frontRequest(response, createMap);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * APP支付获取tn
     */
    @RequestMapping(value = "/appConsume", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public AjaxResult appConsume() {
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setChannelType("08")
                    .setMerId("777290058151764")
                    .setTxnAmt("8888")
                    .setReqReserved("reqReserved")
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .createMap();
            Map<String, String> rspData = UnionPayApi.AppConsumeByMap(reqData);
            // 应答码规范参考open.unionpay.com帮助中心 下载 产品接口规范 《平台接入接口规范-第5部分-附录》
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, "UTF-8")) {
                    logger.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        // 成功,获取tn号
                        String tn = rspData.get("tn");
                        ajax.success(tn);
                    } else {
                        // 其他应答码为失败请排查原因或做失败处理
                        ajax.addError(respCode);
                    }
                } else {
                    logger.error("验证签名失败");
                    // 检查验证签名失败的原因
                    ajax.addError("验证签名失败");
                }
            } else {
                // 未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
                ajax.addError("未获取到返回报文或返回http状态码非200");
            }
            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            logger.info("app>reqMessage>>>" + reqMessage + " rspMessage>>>" + rspMessage);
            return ajax;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 订单状态查询B2C跟B2B查询区别就在于bizType的不同
     */
    @RequestMapping(value = "/query", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void query(HttpServletResponse response) {
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("00")
                    .setTxnSubType("00")
                    .setBizType("000301")
                    .setMerId("777290058151764")
//					.setOrderId("1507214190872")
//					.setTxnTime("20171005223630")
                    .setOrderId("1508488509626")
                    .setTxnTime("20171020163509")
                    .createMap();
            Map<String, String> rspData = UnionPayApi.singleQueryByMap(reqData);
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, "UTF-8")) {
                    logger.info("验证签名成功");
                    if ("00".equals(rspData.get("respCode"))) {//如果查询交易成功
                        //处理被查询交易的应答码逻辑
                        String origRespCode = rspData.get("origRespCode");
                        if ("00".equals(origRespCode)) {
                            //交易成功,更新商户订单状态
                        } else if ("03".equals(origRespCode) ||
                                "04".equals(origRespCode) ||
                                "05".equals(origRespCode)) {
                            //需再次发起交易状态查询交易
                        } else {
                            //其他应答码为失败请排查原因
                        }
                    } else {//查询交易本身失败,或者未查到原交易,检查查询交易报文要素
                    }
                } else {
                    logger.error("验证签名失败");
                    // 检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }
            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 订单状态查询 B2B
     * B2C跟B2B查询区别就在于bizType的不同
     */
    @RequestMapping(value = "/queryB2B", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void queryB2B(HttpServletResponse response) {
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setBizType("000202")
                    .setTxnType("00")
                    .setTxnSubType("00")
                    .setMerId("777290058151764")
                    .setOrderId("1507277885640")
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))
                    .createMap();
            Map<String, String> rspData = UnionPayApi.singleQueryByMap(reqData);
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, "UTF-8")) {
                    logger.info("验证签名成功");
                    if ("00".equals(rspData.get("respCode"))) {//如果查询交易成功
                        //处理被查询交易的应答码逻辑
                        String origRespCode = rspData.get("origRespCode");
                        if ("00".equals(origRespCode)) {
                            //交易成功,更新商户订单状态
                        } else if ("03".equals(origRespCode) ||
                                "04".equals(origRespCode) ||
                                "05".equals(origRespCode)) {
                            //需再次发起交易状态查询交易
                        } else {
                            //其他应答码为失败请排查原因
                        }
                    } else {//查询交易本身失败,或者未查到原交易,检查查询交易报文要素
                    }
                } else {
                    logger.error("验证签名失败");
                    // 检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }
            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @RequestMapping(value = "/refund", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void refund(HttpServletResponse response) {
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("04") //交易类型 04-退货	31-消费撤销
                    .setTxnSubType("00") //交易子类型  默认00
                    .setBizType("000201") //业务类型 B2C网关支付,手机wap支付
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setTxnAmt("6666")
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .setOrigQryId("201710061443208788498") //****原消费交易返回的的queryId,可以从消费交易后台通知接口中或者交易状态查询接口中获取
                    .createMap();
            Map<String, String> rspData = UnionPayApi.backRequestByMap(reqData);
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, "UTF-8")) {
                    logger.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if ("00".equals(respCode)) {
                        //交易已受理,等待接收后台通知更新订单状态,也可以主动发起 查询交易确定交易状态。
                    } else if ("03".equals(respCode) ||
                            "04".equals(respCode) ||
                            "05".equals(respCode)) {
                        //后续需发起交易状态查询交易确定交易状态
                    } else {
                        //其他应答码为失败请排查原因
                    }
                } else {
                    logger.error("验证签名失败");
                    // 检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }

            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 测试通过
     * https://open.unionpay.com/ajweb/help/faq/list?id=95&level=0&from=0
     * java.lang.RuntimeException: Unexpected code Response{protocol=http/1.1, code=500, message=Internal Server Error, url=https://filedownload.test.95516.com/}
     */
    @RequestMapping(value = "/fileTransfer", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void fileTransfer(HttpServletResponse response) {
        try {
//			String settleDate = DateKit.toStr(new Date(), DateKit.UnionDateStampPattern);
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setAccessType("0")
                    .setTxnType("76")  //交易类型 76-对账文件下载
                    .setTxnSubType("01") //交易子类型 01-对账文件下载
                    .setBizType("000000") //业务类型,固定
                    .setMerId("700000000000001")
                    .setSettleDate("0119") //清算日期,如果使用正式商户号测试则要修改成自己想要获取对账文件的日期, 测试环境如果使用777290058151764商户号则固定填写0119
                    .setFileType("00")
                    .createMap();
            //移除默认参数
            reqData.remove("orderId");
            reqData.remove("payTimeout");
            reqData.remove("backUrl");
            reqData.remove("channelType");
            reqData.remove("currencyCode");
            reqData.remove("frontUrl");
            reqData.remove("txnAmt");
            //重新签名
            reqData = UnionPayApiConfig.builder().setSignMap(reqData);
            Map<String, String> rspData = UnionPayApi.fileTransferByMap(reqData);
            String fileContentDispaly = "";
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    logger.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if ("00".equals(respCode)) {
                        String outPutDirectory = "/Users/Javen/Documents/dev/mallplus Pay";
//						String outPutDirectory ="d:\\";
                        // 交易成功,解析返回报文中的fileContent并落地
                        String zipFilePath = AcpService.deCodeFileContent(rspData, outPutDirectory, DemoBase.encoding);
                        //对落地的zip文件解压缩并解析
                        List<String> fileList = DemoBase.unzip(zipFilePath, outPutDirectory);
                        //解析ZM,ZME文件
                        fileContentDispaly = "<br>获取到商户对账文件,并落地到" + outPutDirectory + ",并解压缩 <br>";
                        for (String file : fileList) {
                            if (file.indexOf("ZM_") != -1) {
                                List<Map<Integer, String>> ZmDataList = DemoBase.parseZMFile(file);
                                fileContentDispaly = fileContentDispaly + DemoBase.getFileContentTable(ZmDataList, file);
                            } else if (file.indexOf("ZME_") != -1) {
                                DemoBase.parseZMEFile(file);
                            }
                        }
                        //其他处理
                    } else {
                        //其他应答码为失败请排查原因
                    }
                } else {
                    logger.error("验证签名失败");
                    // 检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }

            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("<html><head></br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + fileContentDispaly + "</head></html>");

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

    }

    /**
     * 信用卡网关还款
     */
    @RequestMapping(value = "/repaymentGateway", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void repaymentGateway(HttpServletResponse response) {
        try {
            Map<String, String> map = new HashMap<String, String>();
            map.put("usr_num", "6221558812340013");//信用卡卡号
            map.put("usr_num2", "6221558812340013");//重复信用卡卡号
            map.put("usr_nm", "全渠道");//信用卡持卡人姓名【无特殊要求尽量不要送】这里填写错误会出现报文格式错误 (5100030)


            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("13") //交易类型 04-退货	31-消费撤销 13 账单支付
                    .setTxnSubType("03") //交易子类型  03 信用卡还款
                    .setBizType("000601")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setBussCode("J1_9800_0000_1")
                    .setMerId("777290058151764")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setTxnAmt("1234")
                    .setBillQueryInfo(AcpService.base64Encode(JSONUtil.toJsonPrettyStr(map), DemoBase.encoding))
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .setFrontUrl(SDKConfig.getConfig().getFrontUrl())
//					.setReqReserved("mallplus Pay repaymentGateway")
                    .createMap();
            UnionPayApi.jfFrontConsume(response, reqData);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 二维码支付
     * 二维码仿真
     * https://open.unionpay.com/ajweb/help/qrcodeFormPage
     */
    @RequestMapping(value = "/qrCodePay", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void qrCodePay(HttpServletResponse response) {
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("01")
                    .setTxnSubType("06")
                    .setBizType("000000")
                    .setChannelType("08") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setAccessType("0")
                    .setAccType("01")
                    .setQrNo("6225058203886110875")
                    .setTermId("00000011")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setTxnAmt("2580")
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .setReqReserved("mallplus Pay qrCodePay")
                    .createMap();
            Map<String, String> rspData = UnionPayApi.backRequestByMap(reqData);
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    logger.info("二维码支付验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        //成功,获取tn号
                        String tn = rspData.get("tn");
                        System.out.println("tn>>>>>>>" + tn);
                    } else {
                        //其他应答码为失败请排查原因或做失败处理
                    }
                } else {
                    logger.error("二维码验证签名失败");
                    //检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }

            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 代收后台建立委托
     */
    @RequestMapping(value = "/jlwtBack", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void jlwtBack(HttpServletResponse response) {
        try {
            //卡号
            String accNoEnc = AcpService.encryptData("6221558812340000", "UTF-8");        //这里测试的时候使用的是测试卡号,正式环境请使用真实卡号

            //姓名,证件类型+证件号码至少二选一必送,手机号可选,贷记卡的cvn2,expired可选。
            Map<String, String> customerInfoMap = new HashMap<String, String>();
            customerInfoMap.put("certifTp", "01");//证件类型
            customerInfoMap.put("certifId", "341126197709218366");//证件号码
            customerInfoMap.put("customerNm", "互联网");//姓名

            customerInfoMap.put("phoneNo", "13552535506");//手机号
            //当卡号为贷记卡的时候cvn2,expired可选上送
            customerInfoMap.put("cvn2", "123");//卡背面的cvn2三位数字
            customerInfoMap.put("expired", "1711");

            String customerInfoStr = AcpService.
                    getCustomerInfoWithEncrypt(customerInfoMap, null, DemoBase.encoding);
//			String customerInfoStr = AcpService.
//					getCustomerInfo(customerInfoMap,null,DemoBase.encoding);


            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("72")
                    .setTxnSubType("11")
                    .setBizType("000501")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setAccessType("0")
                    .setAccType("01")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setAccNo(accNoEnc)
                    .setEncryptCertId(AcpService.getEncryptCertId())//加密证书的certId,配置在acp_sdk.properties文件 acpsdk.encryptCert.path属性下
                    .setCustomerInfo(customerInfoStr)
                    .createMap();
            Map<String, String> rspData = UnionPayApi.backRequestByMap(reqData);
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    logger.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        //成功,获取tn号
                        String tn = rspData.get("tn");
                        System.out.println("tn>>>>>>>" + tn);
                    } else {
                        //其他应答码为失败请排查原因或做失败处理
                    }
                } else {
                    logger.error("验证签名失败");
                    //检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }

            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 代收前台建立委托
     */
    @RequestMapping(value = "/jlwtFront", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void jlwtFront(HttpServletResponse response) {
        try {
            //卡号
            String accNoEnc = AcpService.encryptData("6221558812340000", "UTF-8");        //这里测试的时候使用的是测试卡号,正式环境请使用真实卡号

            //姓名,证件类型+证件号码至少二选一必送,手机号可选,贷记卡的cvn2,expired可选。
            Map<String, String> customerInfoMap = new HashMap<String, String>();
            customerInfoMap.put("certifTp", "01");//证件类型
            customerInfoMap.put("certifId", "341126197709218366");//证件号码
            customerInfoMap.put("customerNm", "互联网");//姓名

            customerInfoMap.put("phoneNo", "13552535506");//手机号
            //当卡号为贷记卡的时候cvn2,expired可选上送
            customerInfoMap.put("cvn2", "123");//卡背面的cvn2三位数字
            customerInfoMap.put("expired", "1711");

            String customerInfoStr = AcpService.
                    getCustomerInfoWithEncrypt(customerInfoMap, null, DemoBase.encoding);
//			String customerInfoStr = AcpService.
//					getCustomerInfo(customerInfoMap,null,DemoBase.encoding);


            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("72")
                    .setTxnSubType("11")
                    .setBizType("000501")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setAccessType("0")
                    .setAccType("01")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setAccNo(accNoEnc)
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .setFrontUrl(SDKConfig.getConfig().getFrontUrl())
                    .setEncryptCertId(AcpService.getEncryptCertId())//加密证书的certId,配置在acp_sdk.properties文件 acpsdk.encryptCert.path属性下
                    .setCustomerInfo(customerInfoStr)
                    .createMap();
            UnionPayApi.frontRequest(response, reqData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解除委托关系
     */
    @RequestMapping(value = "/removeWt", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void removeWt(HttpServletResponse response) {
        try {
            //这里测试的时候使用的是测试卡号,正式环境请使用真实卡号
            String accNoEnc = AcpService.encryptData("6221558812340000", "UTF-8");

            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("74")
                    .setTxnSubType("04")
                    .setBizType("000501")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setAccNo(accNoEnc)
                    .setEncryptCertId(AcpService.getEncryptCertId())//加密证书的certId,配置在acp_sdk.properties文件 acpsdk.encryptCert.path属性下
                    .createMap();
            Map<String, String> rspData = UnionPayApi.backRequestByMap(reqData);
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    logger.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        //成功
                    } else {
                        //其他应答码为失败请排查原因或做失败处理
                    }
                } else {
                    logger.error("验证签名失败");
                    //检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }

            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 代收1102
     */
    @RequestMapping(value = "/daiShou1102", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void daiShou1102(HttpServletResponse response) {
        try {
            //卡号
            String accNoEnc = AcpService.encryptData("6221558812340000", DemoBase.encoding);


            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("11")
                    .setTxnSubType("02")
                    .setBizType("000501")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setAccessType("0")
                    .setAccType("01")
                    .setTxnAmt("8888")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setAccNo(accNoEnc)
                    .setEncryptCertId(AcpService.getEncryptCertId())//加密证书的certId,配置在acp_sdk.properties文件 acpsdk.encryptCert.path属性下
                    .createMap();
            Map<String, String> rspData = UnionPayApi.backRequestByMap(reqData);

            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    logger.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        //交易已受理(不代表交易已成功),等待接收后台通知更新订单状态,也可以主动发起 查询交易确定交易状态。
                        //如果是配置了敏感信息加密,如果需要获取卡号的铭文,可以按以下方法解密卡号
                        //String accNo1 = resmap.get("accNo");
                        //String accNo2 = AcpService.decryptData(accNo1, "UTF-8");  //解密卡号使用的证书是商户签名私钥证书acpsdk.signCert.path
                        //logger.info("解密后的卡号:"+accNo2);

                    } else if (("03").equals(respCode) ||
                            ("04").equals(respCode) ||
                            ("05").equals(respCode)) {
                        //后续需发起交易状态查询交易确定交易状态
                    } else {
                        //其他应答码为失败请排查原因
                    }
                } else {
                    logger.error("验证签名失败");
                    //检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }

            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            response.getWriter().println("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + "");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 无跳转开通状态查询
     */
    @RequestMapping(value = "/openQuery", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void openQuery(HttpServletResponse response) {
        try {
            //卡号
            String accNoEnc = AcpService.encryptData("6216261000000000018", DemoBase.encoding);

            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("00")
                    .setTxnSubType("00")
                    .setBizType("000301")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setAccessType("0")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setAccNo(accNoEnc)
                    .setEncryptCertId(AcpService.getEncryptCertId())//加密证书的certId,配置在acp_sdk.properties文件 acpsdk.encryptCert.path属性下
                    .createMap();
            Map<String, String> rspData = UnionPayApi.backRequestByMap(reqData);
            StringBuffer parseStr = new StringBuffer("");
            if (!rspData.isEmpty()) {
                if (AcpService.validate(rspData, DemoBase.encoding)) {
                    logger.info("验证签名成功");
                    String respCode = rspData.get("respCode");
                    if (("00").equals(respCode)) {
                        //成功
                        parseStr.append("<br>解析敏感信息加密信息如下(如果有):<br>");
                        String customerInfo = rspData.get("customerInfo");
                        if (null != customerInfo) {
                            Map<String, String> cm = AcpService.parseCustomerInfo(customerInfo, "UTF-8");
                            parseStr.append("customerInfo明文: " + cm + "<br>");
                        }
                        String an = rspData.get("accNo");
                        if (null != an) {
                            an = AcpService.decryptData(an, "UTF-8");
                            parseStr.append("accNo明文: " + an);
                        }
                    } else {
                        //其他应答码为失败请排查原因或做失败处理
                    }
                } else {
                    logger.error("验证签名失败");
                    // 检查验证签名失败的原因
                }
            } else {
                //未返回正确的http状态
                logger.error("未获取到返回报文或返回http状态码非200");
            }
            String reqMessage = getHtmlResult(reqData);
            String rspMessage = getHtmlResult(rspData);
            logger.info(getHtmlResult(rspData));
            response.getWriter().write("</br>请求报文:<br/>" + reqMessage + "<br/>" + "应答报文:</br>" + rspMessage + parseStr);

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

    /**
     * 无跳转支付银联侧开通
     */
    @RequestMapping(value = "/openCardFront", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void openCardFront(HttpServletResponse response) {
        try {
            //卡号
            String accNoEnc = AcpService.encryptData("6216261000000000018", "UTF-8");        //这里测试的时候使用的是测试卡号,正式环境请使用真实卡号

            //姓名,证件类型+证件号码至少二选一必送,手机号可选,贷记卡的cvn2,expired可选。
            Map<String, String> customerInfoMap = new HashMap<String, String>();
            customerInfoMap.put("certifTp", "01");//证件类型
            customerInfoMap.put("certifId", "341126197709218366");//证件号码
            customerInfoMap.put("customerNm", "全渠道");//姓名
            customerInfoMap.put("phoneNo", "13552535506");//手机号

            String customerInfoStr = AcpService.
                    getCustomerInfoWithEncrypt(customerInfoMap, null, DemoBase.encoding);
//			String customerInfoStr = AcpService.
//					getCustomerInfo(customerInfoMap,null,DemoBase.encoding);


            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("79")
                    .setTxnSubType("01")
                    .setBizType("000301")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setAccessType("0")
                    .setAccType("01")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setAccNo(accNoEnc)
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .setFrontUrl(SDKConfig.getConfig().getFrontUrl())
                    .setEncryptCertId(AcpService.getEncryptCertId())//加密证书的certId,配置在acp_sdk.properties文件 acpsdk.encryptCert.path属性下
                    .setCustomerInfo(customerInfoStr)
                    .createMap();
            UnionPayApi.frontRequest(response, reqData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 无跳转支付银联测开通并消费
     */
    @RequestMapping(value = "/openAndConsume", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public void openAndConsume(HttpServletResponse response) {
        try {
            //卡号
            String accNoEnc = AcpService.encryptData("6216261000000000018", DemoBase.encoding);


            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("01")
                    .setTxnSubType("01")
                    .setBizType("000301")
                    .setChannelType("07") //渠道类型,07-PC,08-手机
                    .setMerId("777290058151764")
                    .setAccessType("0")
                    .setAccType("01")
                    .setTxnAmt("6363")
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateUtil.format(new Date(), "yyyyMMddHHmmss"))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效
                    .setAccNo(accNoEnc)
                    .setEncryptCertId(AcpService.getEncryptCertId())//加密证书的certId,配置在acp_sdk.properties文件 acpsdk.encryptCert.path属性下
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .setFrontUrl(SDKConfig.getConfig().getFrontUrl())
                    .createMap();
            UnionPayApi.frontRequest(response, reqData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 后台回调
     */
    @RequestMapping(value = "/backRcvResponse", method = {RequestMethod.POST, RequestMethod.GET})
    @ResponseBody
    public String backRcvResponse(HttpServletRequest request) {
        logger.info("BackRcvResponse接收后台通知开始");

        String encoding = "UTF-8";

        String notifyStr = readData(request);
        // 获取银联通知服务器发送的后台通知参数
        Map<String, String> reqParam = getAllRequestParamToMap(notifyStr);
        LogUtil.printRequestLog(reqParam);

        // 重要!验证签名前不要修改reqParam中的键值对的内容,否则会验签不过
        if (!AcpService.validate(reqParam, encoding)) {
            logger.info("后台验证签名结果[失败].");
            // 验签失败,需解决验签问题

        } else {
            logger.info("后台验证签名结果[成功].");
            // 【注:为了安全验签成功才应该写商户的成功处理逻辑】交易成功,更新商户订单状态

            String orderId = reqParam.get("orderId"); // 获取后台通知的数据,其他字段也可用类似方式获取
            String respCode = reqParam.get("respCode");
            // 判断respCode=00、A6后,对涉及资金类的交易,请再发起查询接口查询,确定交易成功后更新数据库。
            logger.info("orderId>>>" + orderId + " respCode>>" + respCode);
        }
        logger.info("BackRcvResponse接收后台通知结束");
        // 返回给银联服务器http 200 状态码
        return "ok";
    }

    /**
     * 前台回调
     */
    @RequestMapping(value = "/frontRcvResponse", method = {RequestMethod.POST, RequestMethod.GET})
    public String frontRcvResponse(HttpServletRequest request, HttpServletResponse response) {
        try {
            logger.info("FrontRcvResponse前台接收报文返回开始");

            String encoding = "UTF-8";
            logger.info("返回报文中encoding=[" + encoding + "]");
            String readData = readData(request);
            Map<String, String> respParam = getAllRequestParamToMap(readData);

            // 打印请求报文
            LogUtil.printRequestLog(respParam);

            Map<String, String> valideData = null;
            StringBuffer page = new StringBuffer();
            if (null != respParam && !respParam.isEmpty()) {
                Iterator<Map.Entry<String, String>> it = respParam.entrySet().iterator();
                valideData = new HashMap<String, String>(respParam.size());
                while (it.hasNext()) {
                    Map.Entry<String, String> e = it.next();
                    String key = (String) e.getKey();
                    String value = (String) e.getValue();
                    value = new String(value.getBytes(encoding), encoding);
                    page.append("<tr><td width=\"30%\" align=\"right\">" + key + "(" + key + ")</td><td>" + value
                            + "</td></tr>");
                    valideData.put(key, value);
                }
            }
            if (!AcpService.validate(valideData, encoding)) {
                page.append("<tr><td width=\"30%\" align=\"right\">前台验证签名结果</td><td>失败</td></tr>");
                logger.info("前台验证签名结果[失败].");
            } else {
                page.append("<tr><td width=\"30%\" align=\"right\">前台验证签名结果</td><td>成功</td></tr>");
                logger.info("前台验证签名结果[成功].");
                String orderId = valideData.get("orderId"); // 其他字段也可用类似方式获取

                String respCode = valideData.get("respCode");
                // 判断respCode=00、A6后,对涉及资金类的交易,请再发起查询接口查询,确定交易成功后更新数据库。
                logger.info("orderId>>>" + orderId + " respCode>>" + respCode);
            }

            request.setAttribute("result", page.toString());
            logger.info("FrontRcvResponse前台接收报文返回结束");

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

        return "utf8_result.html";
    }
}
发布了34 篇原创文章 · 获赞 28 · 访问量 10万+

猜你喜欢

转载自blog.csdn.net/a1439226817/article/details/103896353