当前位置: 首页 > news >正文

java对接银联商务公众号+服务窗支付(1)

java实现银联商务公众号+服务窗对接----支付下单

GitLab地址:https://gitlab.com/982837387/UnionPayGetWay.git
本文对接银联商务公众号+服务窗支付,实现支付下单、订单查询、订单退款、退款查询和订单关闭几个功能,使用到银联商务的公众+服务窗支付接口规范,请自行百度下载。
一、接入前准备
创建maven项目,项目目录如下,各目录功能不再详细介绍,直接看接口和功能。
在这里插入图片描述
二、接口及代码实现
1.支付下单接口
1.1接口规范
接口规范请查看下载的银联商务公众号+服务窗接口规范下单接口部分,这里不做展示。
1.2 代码实现
1.2.1 UnionPayOnlineController代码

package com.unionpay.controller;

import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.HashMap;
import java.util.Map;

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

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.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;



@Controller
@CrossOrigin
@RequestMapping("/lay")	
public class UnionPayOnlineController {
	private final static Logger logger = LoggerFactory.getLogger(UnionPayOnlineController.class);
	
	@Autowired
	private UnifiedOrderServiceimpl unionpayserviceimpl;
	
	/**
	 * 公众号支付下单接口
	 * 调用该接口,跳转到html支付页面
	 * @param request
	 * @param response
	 * @param jsonreq
	 * @return
	 * @throws UnsupportedEncodingException 
	 */
	@RequestMapping(value = "/UnifiedPay", method = RequestMethod.GET)
	public String unionpay(HttpServletRequest request, HttpServletResponse response,Map resultdatamap) throws UnsupportedEncodingException {
		Map datamap = new HashMap();	//客户端请求数据
		String key = UnionPayConstants.GGMD5KEY;					//国光MD5密钥
		
		//---------------------取到URL请求数据----------------------------------------------------
		logger.info("getQueryString:" + request.getQueryString());   //请求url的QueryString
		
			String mid = request.getParameter("mid");
			String tid = request.getParameter("tid");
			String instMid = request.getParameter("instMid");
			String msgSrc = request.getParameter("msgSrc");
			String totalAmount = request.getParameter("totalAmount");
			String payType = request.getParameter("payType");
			String notifyUrl = request.getParameter("notifyUrl");
			String returnUrl = request.getParameter("returnUrl");
			String sign = request.getParameter("sign");
			
		//--------------------step1 对请求字段值进行URLDecoder转码----------------------------
			datamap.put("mid",URLDecoder.decode(mid, "UTF-8"));
			datamap.put("tid",URLDecoder.decode(tid, "UTF-8"));
			datamap.put("instMid",URLDecoder.decode(instMid, "UTF-8"));
			datamap.put("msgSrc",URLDecoder.decode(msgSrc, "UTF-8"));
			datamap.put("totalAmount",URLDecoder.decode(totalAmount, "UTF-8"));
			datamap.put("msgType",URLDecoder.decode(payType, "UTF-8"));
			datamap.put("notifyUrl",URLDecoder.decode(notifyUrl, "UTF-8"));
			datamap.put("returnUrl",URLDecoder.decode(returnUrl, "UTF-8"));
			logger.info("URLDecoder转码后datamap = " + datamap);
		
		//-------------------------step2验证签名------------------------------------------------------
		try {
			if (!PayUtil.verifySign(datamap,key,sign)) {
				resultdatamap.put("returnInfo", "签名错误");
				resultdatamap.put("returnCode", "Bad_Sign");
				//String failureurl = unionpayserviceimpl.CreatefailureUrl(resultmap);
				//logger.info("url = " + failureurl);
				return "failure";	
			}
		//-----------------------step3  验证传参完整性-------------------------- 
			//验证公共参数完整性
			if(!PayUtil.verifyParameter(datamap)) {
				resultdatamap.put("returnCode", "Common_Value_Error");
				resultdatamap.put("returnInfo", "缺少必要公共参数");
				return "failure";
			}
			//验证接口参数完整性
			if(datamap.get("totalAmount").equals("") || datamap.get("msgType").equals("") 
					|| datamap.get("notifyUrl").equals("") || datamap.get("returnUrl").equals("") ) {
				resultdatamap.put("returnCode", "Value_Error");
				resultdatamap.put("returnInfo", "缺少必要接口参数,必传接口参数不允许为空");
				return "failure";
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			resultdatamap.put("returnCode", "System_Error");
			resultdatamap.put("returnInfo", "系统异常");
			return "failure";
		}
		//-----------------------step4 传值并生成链接跳转到支付页面--------------------------------
		//Map resultdatamap = new HashMap();
		resultdatamap.put("mid", mid);					    //商户号
		resultdatamap.put("tid", tid);						//终端号
		resultdatamap.put("instMid", instMid);				//机构商户号
		resultdatamap.put("msgSrc", msgSrc);				//消息来源
		resultdatamap.put("totalAmount", totalAmount); 		//总金额
		resultdatamap.put("msgType", payType);				//支付类型
		resultdatamap.put("notifyUrl", notifyUrl);			//支付结果通知
		resultdatamap.put("returnUrl", returnUrl);			//网页跳转地址
		resultdatamap.put("merOrderId", unionpayserviceimpl.CreateOrderID());	//生成商户订单号
		logger.info("resultdatamap = " + resultdatamap);
		//根据payType判断回调到哪个支付页面
		if(resultdatamap.get("msgType").equals("WXPay.jsPay")) {	//微信支付
			return "wxunionpay";
		}else {
			return "aliunionpay";									//支付宝支付
		}
	}
	
	/**
	 * a支付失败页面
	 * @param request
	 * @param response
	 * @param returnCode
	 * @param map
	 * @return
	 */
	@RequestMapping(value = "/failure", method = RequestMethod.GET)
	public String failure(HttpServletRequest request, HttpServletResponse response,String returnCode,Map map) {
		
		map.put("returnCode", returnCode); 
		
		return "failure";	
	}
	
	/**
	 * a根据支付页面请求,调起支付下单
	 * @param request
	 * @param response
	 * @param totalAmount
	 * @param msgType
	 * @return
	 */
	@RequestMapping(value = "/unifiedpay", method = RequestMethod.GET)
	public String index(HttpServletRequest request, HttpServletResponse response, Map map) {
		Map reqmap = new HashMap();
		//---------------------取到URL请求数据-----------------------------
		logger.info("unifiedpay getQueryString:" + request.getQueryString());    //请求url的QueryString
			String mid = request.getParameter("mid");
			String tid = request.getParameter("tid");
			String instMid = request.getParameter("instMid");
			String msgSrc = request.getParameter("msgSrc");
			String totalAmount = request.getParameter("totalAmount");
			String YtotalAmount = PayUtil.changeY2F(totalAmount);	//元转分
			logger.info("YtotalAmount = " + YtotalAmount);
			String msgType = request.getParameter("msgType");
			String notifyUrl = request.getParameter("notifyUrl");
			String returnUrl = request.getParameter("returnUrl");
			String merOrderId = request.getParameter("merOrderId");
			
			reqmap.put("mid", mid);
			reqmap.put("tid", tid);
			reqmap.put("instMid", instMid);
			reqmap.put("msgSrc", msgSrc);
			reqmap.put("totalAmount", YtotalAmount);
			reqmap.put("msgType", msgType);
			reqmap.put("notifyUrl", notifyUrl);
			reqmap.put("returnUrl", returnUrl);
			reqmap.put("merOrderId", merOrderId);
			logger.info("reqmap = " + reqmap);
		String url = "";
		try {
			url = unionpayserviceimpl.UnifiedOrder(reqmap);
			//logger.info("请求URL = " + url);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
//		if(url.equals("缺少必要参数,请核实后再进行下单")) {
//			map.put("returnCode", "缺少必要参数,请核实后再进行下单");
//			return "failure";
//		}
		return "redirect:" + url; //重定向到下单页面	
	}
	
}

1.2.2 UnionpayServiceimpl代码
本部分代码为银联商务支付下单接口服务。

/**
	 * 	银联商务支付下单
	 * return map
	 * @throws UnsupportedEncodingException 
	 */
	@Override
	public String UnifiedOrder(Map map) throws UnsupportedEncodingException {
		// TODO Auto-generated method stub
		Map reqmap = new HashMap(); //请求银联商务map
			reqmap.put("mid", map.get("mid"));			//商户号
			reqmap.put("tid", map.get("tid"));			//终端号
			reqmap.put("instMid", map.get("instMid"));
			reqmap.put("msgSrc", map.get("msgSrc"));	//消息来源
			reqmap.put("msgId", "UnionPay_F001");		//自定义
			reqmap.put("msgType", map.get("msgType"));	//支付类型,前端传入
			
			//报文请求时间
			String aligetTime = PayUtil.aligetTime();
			logger.info("end_time = " + aligetTime);
			reqmap.put("requestTimestamp", aligetTime);	
			
			//商户订单号
			//reqmap.put("msgSrcId", this.msgSrcId);	//来源编号
//			String orderid = GGitUtil.createOrderID();
//			StringBuffer buff = new StringBuffer(); 
//			buff.append(this.msgSrcId);
//			buff.append(orderid);
			reqmap.put("merOrderId", map.get("merOrderId"));
			
			reqmap.put("originalAmount", map.get("totalAmount"));	//前端传入
			reqmap.put("totalAmount",map.get("totalAmount"));	//订单金额
			reqmap.put("notifyUrl", map.get("notifyUrl"));	//支付结果通知地址
			reqmap.put("returnUrl", map.get("returnUrl"));	//网页跳转地址
			
			//生成待签名字符串并进行MD5加密
			String builderSignStr = "";
			try {
				  builderSignStr = PayUtil.builderSignStr(reqmap,UnionPayConstants.MD5KEY);
				//signString = PayUtil.generateSignature(reqmap, UnionPayConstants.MD5KEY);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			reqmap.put("sign", builderSignStr);
			logger.info("reqmap= " + reqmap);
			
			//拼接请求URL
			StringBuffer url = new StringBuffer();
			try {
				url.append("https://qr-test2.chinaums.com/netpay-portal/webpay/pay.do?");
				url.append("requestTimestamp=" + URLEncoder.encode((String) reqmap.get("requestTimestamp"), "UTF-8") +
						"&mid=" + URLEncoder.encode((String) reqmap.get("mid"), "UTF-8") + 
						"&tid="+ URLEncoder.encode((String) reqmap.get("tid"), "UTF-8") + 
						"&instMid=" + URLEncoder.encode((String) reqmap.get("instMid"), "UTF-8") + 
						"&msgSrc=" + URLEncoder.encode((String) reqmap.get("msgSrc"), "UTF-8") + 
						"&merOrderId=" + URLEncoder.encode((String) reqmap.get("merOrderId"), "UTF-8") + 
						"&totalAmount=" + URLEncoder.encode((String) reqmap.get("totalAmount"), "UTF-8") + 
						"&msgId=" + URLEncoder.encode((String) reqmap.get("msgId"), "UTF-8") + 
						"&msgType=" + URLEncoder.encode((String) reqmap.get("msgType"), "UTF-8") + 
						"&originalAmount=" + URLEncoder.encode((String) reqmap.get("originalAmount"), "UTF-8") + 
						"¬ifyUrl=" + URLEncoder.encode((String) reqmap.get("notifyUrl"), "UTF-8") + 
						"&returnUrl=" + URLEncoder.encode((String) reqmap.get("returnUrl"), "UTF-8") + 
						"&sign=" + URLEncoder.encode((String) reqmap.get("sign"), "UTF-8"));
				logger.info("银联商务下单url = " + url);
			} catch (Exception e) {
				// TODO: handle exception
				return "缺少必要参数,请核实后再进行下单";
			}
		return url.toString();
	}

1.3 支付结果截图
在下单接口中,我先在写了一个支付的html页面,用于显示支付信息,用户点击“去支付”按钮调起图二支付页面,支付完成时,用户点击“完成”按钮,跳转到程序中指定的returnurl地址中,支付结果通知到notifyurl地址中。
支付下单参数由银联商务分配的参数填入。

访问地址:http://172.20.10.2:8080/UnionPay/lay/UnifiedPay(本地环境访问)
支付连接为:http://172.20.10.2:8080/UnionPay/lay/UnifiedPay?mid=******&tid=******&instMid=******&msgSrc=******&payType=WXPay.jsPay&totalAmount=0.11¬ifyUrl=http%3A%2F%2F******&returnUrl=http%3A%2F%2F******&sign=B2AD890DD4636C9A9AEA03F265BE695A
在这里插入图片描述
在这里插入图片描述根据博友的需求,这里增加下银商验签部分代码

 /**
   * 生成 MD5
   *
   * @param data
   *            待处理数据
   * @return MD5结果
   */
  public static String MD5(String data) throws Exception {
   java.security.MessageDigest md = MessageDigest.getInstance("MD5");
   byte[] array = md.digest(data.getBytes("UTF-8"));
   StringBuilder sb = new StringBuilder();
   for (byte item : array) {
    sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
   }
   return sb.toString().toUpperCase();
  }

 /**
  * 生成待签名数据
  * @param params
  * @return
  * @throws Exception 
  */
    public static String builderSignStr(Map<String, Object> params,String md5key) throws Exception {
         Set<String> keySet = params.keySet();
         List<String>keyList = new ArrayList<String>(keySet);
         Collections.sort(keyList);
         StringBuilder sb = new StringBuilder();
         for (String key : keyList) {
             sb.append(key);
             sb.append("=");
             sb.append(params.get(key));
             sb.append("&");
         }
         sb.deleteCharAt(sb.length() - 1); //去掉最后一个&
         sb.append(md5key);
         logger.info("builderSignStr= " + sb.toString());
         logger.info("验证sign:" + MD5(sb.toString()).toUpperCase());
         return MD5(sb.toString()).toUpperCase();
     }

相关文章:

  • java对接银联商务公众号+服务窗支付(2)
  • java对接银联商务公众号+服务窗支付(3)
  • java对接银联商务公众号+服务窗支付(4)
  • java对接银联商务公众号+服务窗支付(5)
  • java对接银联商务扫码支付
  • 报错:Invalid bound statement (not found): com.wshy.example.dao.UserDao.getUsers
  • Field userDao ....service.impl...'com.lzj.springcloud.dao.UserDao' that could not be found
  • java对接银联商务扫码支付(银联商务扫码支付文档)
  • Java中拦截器的使用
  • 记项目中出现的数据库若干问题和注意事项
  • 工行icbc 在线支付jar包下载及maven导入本地库
  • 工行聚合支付二维码扫码付对接流程及代码实现
  • Java常量类配置--json文件方式
  • Java中File类的常用操作及项目中的使用
  • Java Utils工具类--jsonmap
  • 5分钟即可掌握的前端高效利器:JavaScript 策略模式
  • 78. Subsets
  • IDEA 插件开发入门教程
  • JavaScript 基础知识 - 入门篇(一)
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • SpringBoot几种定时任务的实现方式
  • text-decoration与color属性
  • 百度地图API标注+时间轴组件
  • 笨办法学C 练习34:动态数组
  • 翻译:Hystrix - How To Use
  • 构造函数(constructor)与原型链(prototype)关系
  • 聚簇索引和非聚簇索引
  • 聊聊directory traversal attack
  • 我感觉这是史上最牛的防sql注入方法类
  • 想晋级高级工程师只知道表面是不够的!Git内部原理介绍
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​ssh免密码登录设置及问题总结
  • #NOIP 2014# day.2 T2 寻找道路
  • (delphi11最新学习资料) Object Pascal 学习笔记---第8章第2节(共同的基类)
  • (html5)在移动端input输入搜索项后 输入法下面为什么不想百度那样出现前往? 而我的出现的是换行...
  • (LNMP) How To Install Linux, nginx, MySQL, PHP
  • (分布式缓存)Redis分片集群
  • (已解决)什么是vue导航守卫
  • (原創) 是否该学PetShop将Model和BLL分开? (.NET) (N-Tier) (PetShop) (OO)
  • (转)shell中括号的特殊用法 linux if多条件判断
  • ***原理与防范
  • .describe() python_Python-Win32com-Excel
  • .NET Core、DNX、DNU、DNVM、MVC6学习资料
  • .Net调用Java编写的WebServices返回值为Null的解决方法(SoapUI工具测试有返回值)
  • .net实现客户区延伸至至非客户区
  • @Data注解的作用
  • [Android]一个简单使用Handler做Timer的例子
  • [Android实例] 保持屏幕长亮的两种方法 [转]
  • [AutoSar]状态管理(五)Dcm与BswM、EcuM的复位实现
  • [BetterExplained]书写是为了更好的思考(转载)
  • [C++打怪升级]--学习总目录
  • [CF543A]/[CF544C]Writing Code
  • [delphi]保证程序只运行一个实例