美文网首页
银联手机控件支付+后台接口部署+支付流程说明

银联手机控件支付+后台接口部署+支付流程说明

作者: Arison | 来源:发表于2018-06-29 17:10 被阅读611次

说明

由于没有正式的银联商户号,只能用测试的银联商户号进行测试;
正式的银联商户号需要提交资料给银联审核,并需要支付一笔费用,大概几千块钱吧,以后还要根据你的支付量来抽成。先不管那么多吧,先把测试流程走通,后面切换到正式商户号就问题不大了;

官网链接

搭建测试环境

  • Android 支付客户端:
    需要接入银联官方支付SDK,银联官方支付SDK是eclipse版本的,个人感觉不是很友好,所以把它改造成android studio结构的项目,方便调式开发。
    官方SDK和DEMO下载地址-eclipse版本
    image.png

改造迁移到Android studio版本的DEMO下载地址【代码整理中,稍后提供...】

  • 后台银联支付程序
    【代码整理中,稍后提供...】

测试流程

第一步:手机支付之前,需要调用获取tn订单流水号:

接口地址:http://qq784602719.imwork.net:43580/Sockets/unionpay/appConsume

image.png

第二步:手机支付回调接口:

接口地址:http://qq784602719.imwork.net:43580/Sockets/unionpay/backRcvResponse

image.png

支付通知回调 【服务器获取银联支付回调,获取订单号orderId和原交易号queryId】

{
"bizType":"000201",
"signPubKeyCert":"-----BEGIN CERTIFICATE-----\r\nMIIEQzCCAyugAwIBAgIFEBJJZVgwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMC\r\nQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhv\r\ncml0eTEXMBUGA1UEAxMOQ0ZDQSBURVNUIE9DQTEwHhcNMTcxMTAxMDcyNDA4WhcN\r\nMjAxMTAxMDcyNDA4WjB3MQswCQYDVQQGEwJjbjESMBAGA1UEChMJQ0ZDQSBPQ0Ex\r\nMQ4wDAYDVQQLEwVDVVBSQTEUMBIGA1UECxMLRW50ZXJwcmlzZXMxLjAsBgNVBAMU\r\nJTA0MUBaMjAxNy0xMS0xQDAwMDQwMDAwOlNJR05AMDAwMDAwMDEwggEiMA0GCSqG\r\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDIWO6AESrg+34HgbU9mSpgef0sl6avr1d\r\nbD/IjjZYM63SoQi3CZHZUyoyzBKodRzowJrwXmd+hCmdcIfavdvfwi6x+ptJNp9d\r\nEtpfEAnJk+4quriQFj1dNiv6uP8ARgn07UMhgdYB7D8aA1j77Yk1ROx7+LFeo7rZ\r\nDdde2U1opPxjIqOPqiPno78JMXpFn7LiGPXu75bwY2rYIGEEImnypgiYuW1vo9UO\r\nG47NMWTnsIdy68FquPSw5FKp5foL825GNX3oJSZui8d2UDkMLBasf06Jz0JKz5AV\r\nblaI+s24/iCfo8r+6WaCs8e6BDkaijJkR/bvRCQeQpbX3V8WoTLVAgMBAAGjgfQw\r\ngfEwHwYDVR0jBBgwFoAUz3CdYeudfC6498sCQPcJnf4zdIAwSAYDVR0gBEEwPzA9\r\nBghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNu\r\nL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNh\r\nLmNvbS5jbi9SU0EvY3JsMjQ4NzIuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU\r\nmQQLyuqYjES7qKO+zOkzEbvdFwgwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF\r\nBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAujhBuOcuxA+VzoUH84uoFt5aaBM3vGlpW\r\nKVMz6BUsLbIpp1ho5h+LaMnxMs6jdXXDh/du8X5SKMaIddiLw7ujZy1LibKy2jYi\r\nYYfs3tbZ0ffCKQtv78vCgC+IxUUurALY4w58fRLLdu8u8p9jyRFHsQEwSq+W5+bP\r\nMTh2w7cDd9h+6KoCN6AMI1Ly7MxRIhCbNBL9bzaxF9B5GK86ARY7ixkuDCEl4XCF\r\nJGxeoye9R46NqZ6AA/k97mJun//gmUjStmb9PUXA59fR5suAB5o/5lBySZ8UXkrI\r\npp/iLT8vIl1hNgLh0Ghs7DBSx99I+S3VuUzjHNxL6fGRhlix7Rb8\r\n-----END CERTIFICATE-----",
"orderId":"1530258613483",
"txnSubType":"01",
"signature":"A7ejZYsORlSPGcag5Y17dYldv5pI3x+l7JbrWfN2QicuugofW1wgu5IHxBzhwGX0kS2vbIOYI0bkFruNNtKtq4mOwdIEOUR8guUU2rckxRNrRiWYdJazcgUtKv8qS14UvBdzc7vzt8gWSbzAjzJH8eAw+JLm/ABP54XwA96/cIwcS9S+0luHnG+dKBiK30/xaLG9Bc1bZDnawILOltjW+IdkkQiiOKtmKl5nVpEjYgqfe0ZjnzBemqYQbyFmGtB/RjxEyApq6NMfeNoaAv81aLbx3jdwyWK8Exc49ZUykDtShbZw2xRDrSLwBGtXWfJMQRXO170mOH9JE9iIAYsRsA==",
"traceNo":"161203",
"settleAmt":"1",
"settleCurrencyCode":"156",
"settleDate":"0629",
"txnType":"01",
"encoding":"UTF-8",
"version":"5.1.0",
"queryId":"981806291550131612038",
"accessType":"0",
"reqReserved":"reqReserved",
"respMsg":"成功[0000000]",
"traceTime":"0629155013",
"txnTime":"20180629155013",
"merId":"777290058159097",
"currencyCode":"156",
"respCode":"00",
"signMethod":"01",
"txnAmt":"1"
}

根据手机支付成功之后,银联中心对你自己写的后台接口进行回调获得的参数中,我们拿到关键参数:
"orderId":"1530258613483"

进入银联技术开发平台,点击我的测试,我的产品。这里我选择的是手机控件支付测试。其它类型的产品测试类似:


image.png

根据图中测试展示,手机控件支付成功!订单号也显示在这里了。

支付订单退款

退款接口:http://qq784602719.imwork.net:43580/Sockets/unionpay/refund
关键参数:原交易号queryId 和退款金额
请求方式:POST

image.png

"queryId":"981806291550131612038",
根据支付成功回调,我们知道原交易号queryId为:981806291550131612038

image.png

退款结果:


image.png

退款回调参数:(退款成功之后,后台回调接口会被银联系统调用)


image.png
{
"bizType":"000201",
"signPubKeyCert":"-----BEGIN CERTIFICATE-----\r\nMIIEQzCCAyugAwIBAgIFEBJJZVgwDQYJKoZIhvcNAQEFBQAwWDELMAkGA1UEBhMC\r\nQ04xMDAuBgNVBAoTJ0NoaW5hIEZpbmFuY2lhbCBDZXJ0aWZpY2F0aW9uIEF1dGhv\r\ncml0eTEXMBUGA1UEAxMOQ0ZDQSBURVNUIE9DQTEwHhcNMTcxMTAxMDcyNDA4WhcN\r\nMjAxMTAxMDcyNDA4WjB3MQswCQYDVQQGEwJjbjESMBAGA1UEChMJQ0ZDQSBPQ0Ex\r\nMQ4wDAYDVQQLEwVDVVBSQTEUMBIGA1UECxMLRW50ZXJwcmlzZXMxLjAsBgNVBAMU\r\nJTA0MUBaMjAxNy0xMS0xQDAwMDQwMDAwOlNJR05AMDAwMDAwMDEwggEiMA0GCSqG\r\nSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDIWO6AESrg+34HgbU9mSpgef0sl6avr1d\r\nbD/IjjZYM63SoQi3CZHZUyoyzBKodRzowJrwXmd+hCmdcIfavdvfwi6x+ptJNp9d\r\nEtpfEAnJk+4quriQFj1dNiv6uP8ARgn07UMhgdYB7D8aA1j77Yk1ROx7+LFeo7rZ\r\nDdde2U1opPxjIqOPqiPno78JMXpFn7LiGPXu75bwY2rYIGEEImnypgiYuW1vo9UO\r\nG47NMWTnsIdy68FquPSw5FKp5foL825GNX3oJSZui8d2UDkMLBasf06Jz0JKz5AV\r\nblaI+s24/iCfo8r+6WaCs8e6BDkaijJkR/bvRCQeQpbX3V8WoTLVAgMBAAGjgfQw\r\ngfEwHwYDVR0jBBgwFoAUz3CdYeudfC6498sCQPcJnf4zdIAwSAYDVR0gBEEwPzA9\r\nBghggRyG7yoBATAxMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmNmY2EuY29tLmNu\r\nL3VzL3VzLTE0Lmh0bTA5BgNVHR8EMjAwMC6gLKAqhihodHRwOi8vdWNybC5jZmNh\r\nLmNvbS5jbi9SU0EvY3JsMjQ4NzIuY3JsMAsGA1UdDwQEAwID6DAdBgNVHQ4EFgQU\r\nmQQLyuqYjES7qKO+zOkzEbvdFwgwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF\r\nBwMEMA0GCSqGSIb3DQEBBQUAA4IBAQAujhBuOcuxA+VzoUH84uoFt5aaBM3vGlpW\r\nKVMz6BUsLbIpp1ho5h+LaMnxMs6jdXXDh/du8X5SKMaIddiLw7ujZy1LibKy2jYi\r\nYYfs3tbZ0ffCKQtv78vCgC+IxUUurALY4w58fRLLdu8u8p9jyRFHsQEwSq+W5+bP\r\nMTh2w7cDd9h+6KoCN6AMI1Ly7MxRIhCbNBL9bzaxF9B5GK86ARY7ixkuDCEl4XCF\r\nJGxeoye9R46NqZ6AA/k97mJun//gmUjStmb9PUXA59fR5suAB5o/5lBySZ8UXkrI\r\npp/iLT8vIl1hNgLh0Ghs7DBSx99I+S3VuUzjHNxL6fGRhlix7Rb8\r\n-----END CERTIFICATE-----",
"orderId":"1530260716679",
"txnSubType":"00",
"signature":"YhjN2h8ZnhmWK4ck/Kb1FtGejeXoHsz1sQbx2Ns4bCa7Y8OYYaF3C4CHLqa4IrpONuHC6KO9dJ1v+QCEIQJ+sr2iwxspByzSmdrETJBNHfdO2CdjWvTUxXEGK9cx9oIjXuPOd9EjnATsMpihlfVA69S/VVS4iqrTJoq/H68sC+ATpDBGuZQKq1RzKtJl7Yd2A1yVBpXtJAK6Odey2GT/n7ZUF4P82OUIXphKz61pxJ0ZInkGamJwwH51FhAJ7MY/crO4VlAR9BFqzTzEURxuaolyGA9+W1ssMcW9cxVyrefPcLGrgEX4pUBlj6STus2IhIgo5deogZ7b1BmIL/1HIg==",
"traceNo":"275003",
"settleAmt":"1",
"settleCurrencyCode":"156",
"settleDate":"0629",
"txnType":"04",
"encoding":"UTF-8",
"version":"5.1.0",
"queryId":"981806291625162750038",
"accessType":"0",
"respMsg":"成功[0000000]",
"traceTime":"0629162516",
"txnTime":"20180629162516",
"merId":"777290058159097",
"origQryId":"981806291550131612038",
"currencyCode":"156",
"respCode":"00",
"signMethod":"01",
"txnAmt":"1"
}
image.png

到这里我们可以看到退款订单号 跟回调接口中返回参数 中的退款订单号一致,退款测试成功!!!

其它的关于支付的一些测试工作,只要按照银联文档进行,都是类似的情况,关键是看银联支付文档。这里也就不一一测试了。

支付API文档地址:

https://open.unionpay.com/ajweb/help/api

image.png

订单交易状态查询:

http://qq784602719.imwork.net:43580/Sockets/unionpay/query

关键参数:订单号和txnTime 交易时间

image.png

接口代码:

@Controller
@RequestMapping("/unionpay")
public class UnionPayController {
    private static final Logger logger = LoggerFactory.getLogger(UnionPayController.class);
    private AjaxResult ajax = new AjaxResult();
    
    @RequestMapping("")
    @ResponseBody
    public String index() {
        logger.info("欢迎使用银联支付接口");
        return "欢迎使用银联支付接口";
    }
    
    /**
     * APP支付获取tn
     */
    @RequestMapping(value = "/appConsume",method={RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public AjaxResult appConsume() {
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setChannelType("08")//渠道类型 channelType  08是移动
                    .setMerId("777290058159097")//商户代码  merId 777290058159097
                    .setTxnAmt("1")//单位为分,不能带小数点,样例:1元送100
                    .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;
    }
    
    
    /**
     * 组装请求,返回报文字符串用于显示
     * 
     * @param data
     * @return {String}
     */
    public static String getHtmlResult(Map<String, String> data) {

        TreeMap<String, String> tree = new TreeMap<String, String>();
        Iterator<Entry<String, String>> it = data.entrySet().iterator();
        while (it.hasNext()) {
            Entry<String, String> en = it.next();
            tree.put(en.getKey(), en.getValue());
        }
        it = tree.entrySet().iterator();
        StringBuffer sf = new StringBuffer();
        while (it.hasNext()) {
            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();
    }
    
    
    /**
     * 订单状态查询
     * B2C跟B2B查询区别就在于bizType的不同
     */
    @RequestMapping(value = "/query",method={RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public void query(HttpServletResponse response,
            @RequestParam("orderId") String orderId,
            @RequestParam("txnTime") String txnTime){
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("00")
                    .setTxnSubType("00")
                    .setBizType("000301")
                    .setMerId("777290058159097")
                    .setOrderId(orderId)
                    .setTxnTime(txnTime)
                    .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();
        }
    }
    
    /**
     * 退款接口
     * @param response
     * @param origOryId  :原始交易订单号
     * @param free :退款金额
     */
    @RequestMapping(value = "/refund",method={RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public void refund(HttpServletResponse response,
            @RequestParam("origOryId") String origOryId,
            @RequestParam("free")  String free){
        try {
            Map<String, String> reqData = UnionPayApiConfig.builder()
                    .setTxnType("04") //交易类型 04-退货  31-消费撤销
                    .setTxnSubType("00") //交易子类型  默认00
                    .setBizType("000201") //业务类型 B2C网关支付,手机wap支付
                    .setChannelType("08") //渠道类型,07-PC,08-手机
                    .setMerId("777290058159097")//商户号
                    .setOrderId(String.valueOf(System.currentTimeMillis()))//商户订单号,8-40位数字字母,不能含“-”或“_”,可以自行定制规则,重新产生,不同于原消费
                    .setTxnTime(DateKit.toStr(new Date(), DateKit.UnionTimeStampPattern))//订单发送时间,格式为YYYYMMDDhhmmss,必须取当前时间,否则会报txnTime无效   
                    .setTxnAmt(free)
                    .setBackUrl(SDKConfig.getConfig().getBackUrl())
                    .setOrigQryId(origOryId) //****原消费交易返回的的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();
        }
    }
    
    /**
     * 后台回调
     */
    @RequestMapping(value = "/backRcvResponse",method={RequestMethod.POST,RequestMethod.GET})
    @ResponseBody
    public String backRcvResponse(HttpServletRequest request) {
        logger.info("BackRcvResponse接收后台通知开始");

        String encoding = "UTF-8";

        //String notifyStr = HttpKit.readData(request);
        //System.out.println("返回参数 str:"+notifyStr);
        // 获取银联通知服务器发送的后台通知参数
        //Map<String, String> reqParam = getAllRequestParamToMap(notifyStr);
        Map<String, String> reqParam = getAllRequestParam(request);
        System.out.println("返回参数 map:"+JSON.toJSONString(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 = HttpKit.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<Entry<String, String>> it = respParam.entrySet().iterator();
                valideData = new HashMap<String, String>(respParam.size());
                while (it.hasNext()) {
                    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";
    }

    
    /**
     * 获取请求参数中所有的信息
     * 
     * @param request
     * @return
     */
    public static Map<String, String> getAllRequestParam(final HttpServletRequest request) {
        Map<String, String> res = new HashMap<String, String>();
        Enumeration<?> temp = request.getParameterNames();
        if (null != temp) {
            while (temp.hasMoreElements()) {
                String en = (String) temp.nextElement();
                String value = request.getParameter(en);
                res.put(en, value);
                //在报文上送时,如果字段的值为空,则不上送<下面的处理为在获取所有参数数据时,判断若值为空,则删除这个字段>
                //System.out.println("ServletUtil类247行  temp数据的键=="+en+"     值==="+value);
                if (null == res.get(en) || "".equals(res.get(en))) {
                    res.remove(en);
                }
            }
        }
        return res;
    }
    
    /**
     * 将回调参数转为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;
    }

}

相关文章

  • 银联手机控件支付+后台接口部署+支付流程说明

    说明 由于没有正式的银联商户号,只能用测试的银联商户号进行测试;正式的银联商户号需要提交资料给银联审核,并需要支付...

  • 银联云闪付控件支付--python版本签名、验签代码

    说明 接口适用于 所有接入中国银联全渠道平台的商户 商户版银联在线支付网关产品及银联手机支付—银联手机支付—手机控...

  • iOS制作银联支付SDK过程

    本文首发地址 这里很有必要记录一下银联支付的iOS控件的下载地址银联支付SDK下载地址git下载地址选择手机控件下...

  • 收录 : iOS支付开发

    iOS 银联支付开发流程iOS 微信支付开发流程iOS 支付宝支付开发流程iOS Apple Pay开发流程App...

  • iOS银联支付集成

    项目中需要用到银联支付,简单的记录下集成过程与集成中遇到的问题。 一、到银联支付开放平台下载SDK,银联手机控件支...

  • iOS 银联支付 newSizeWithFont:forWidt

    iOS 银联支付,打开银联控件报错: newSizeWithFont:forWidth:lineBreakMode...

  • 银联支付的接口申请

    前一段时间在帮公司申请各种支付接口,在银联支付接口消耗了不少时间,其实银联支付申请还是比较简单的(不用上传app截...

  • 第三方支付流程

    支付 一.支付宝和银联的支付流程 常用的支付方式有: 1、支付宝支付 https://openhome.alipa...

  • 支付

    支付 1.支付宝和银联的支付流程 常用的支付方式有: 1、支付宝支付 https://openhome.alipa...

  • iOS支付封装

    主要包括:微信前段后台掉起支付、支付宝国内,国外掉起支付 银联、苹果支付 下载地址: https://github...

网友评论

      本文标题:银联手机控件支付+后台接口部署+支付流程说明

      本文链接:https://www.haomeiwen.com/subject/wjuayftx.html