专业编程基础技术教程

网站首页 > 基础教程 正文

java如何调用支付宝和微信支付功能

ccvgpt 2024-11-30 19:13:14 基础教程 2 ℃

最近项目上用到了调用微信和支付宝的第三方支付接口,因为以前没用过,所以这次用到了之后总结一下分享给大家,这里介绍两种支付方式,即app支付和扫码支付方式。

一、app支付(这里只介绍java端调用支付,安卓或ios端自己参考相关的调用文档)

java如何调用支付宝和微信支付功能

首先可以看一看项目支付流程(图解)

1. 在页面上选择支付方式(微信或支付宝)

2. 由相应的客户端调用相应的支付方式进入相应的支付页面(安卓或ios调用支付接口并进入微信或支付宝支付页面,显示支付的信息)

3. 输入密码进行支付

4. 调用支付结果接口,来返回支付成功与否


四图分别是选择支付方式、微信支付页面、支付宝支付页面、微信支付结果(成功)页面

也是基本的支付三个步骤。

一、先看微信支付:

在调用微信支付之前你应该已经下单成功(即订单信息入库成功),这里需要几个值:

OrderName(订单名称),orderNumber(订单编号,唯一),amount(金额), prepayId(交易会话id)

前三个参数直接从数据库里获取。prepayid是什么?可以具体看微信支付文档,我们可以从下单接口中返回获得这个会话id并且需要入库,这个参数最重要的作用是用于第一次我们没有支付,但已经生成了一个待支付的订单。这种情况下我们不需要再次去调用下单接口返回prepayId,因为我们已经生成过了这个值

下面看手机端jsp页面的js代码:

//在页面选择微信,点击确认支付???
????????????function?wxPay(outTradeNo){??
????????????????var?orderType="0";?//路线?订单???
?????????????????$.ajax({??
????????????????????????url?:'<%=basePath%>client/travel/getWXClientPayInfo.do?outTradeNo='+outTradeNo+'&orderType='+orderType,??
????????????????????????cache?:?false,??
????????????????????????type?:?"get",??
????????????????????????success?:?function(data)??
????????????????????????{??
??????????????????????????????
????????????????????????????if(data!=null){??
????????????????????????????????data?=?jQuery.parseJSON(data);??
??????????????????????????????????
????????????????????????????????var?u?=?navigator.userAgent;??
????????????????????????????????var?isAndroid?=?u.indexOf('Android')?>?-1?||?u.indexOf('Adr')?>?-1;?//android终端??
????????????????????????????????var?isiOS?=?!!u.match(/\(i[^;]+;(?U;)??CPU.+Mac?OS?X/);?//ios终端??
????????????????????????????????if(isAndroid){??
????????????????????????????????????ClientInterface.pay(outTradeNo,data.prepayid,data.noncestr,data.timestamp,data.sign,orderType);??
????????????????????????????????}else?if(isiOS){??
????????????????????????????????????window.location.href='http://localhost/pay/'+outTradeNo+';'+data.prepayid+";"+data.noncestr+";"+data.timestamp+";"+data.sign+";"+orderType;??
????????????????????????????????}?????
??????????????????????????????????
?????????????????????????????}???
????????????????????????}??
????????????????????});??
????????????}?

这里outTradeNo即是唯一的订单编号,orderType是自己定义的订单类型,这里的ajax就是根据这两个参数去后台去操作下单,然后返回必要的参数给安卓或ios调用

然后看后台的这个方法:

/**获取微信客户端支付信息 如 签名 随机数等
	 * @param page
	 * @throws Exception
	 */
	@RequestMapping(value="/getWXClientPayInfo")
	@ResponseBody
	public String getWeixinPayInfo(HttpServletRequest request) throws Exception{
		String orderNumber = request.getParameter("outTradeNo");
		String orderType = request.getParameter("orderType");
		Map<String, Object> map=new HashMap<String, Object>();
		map.put("orderNumber", orderNumber);
		map.put("type", orderType);
		//获取订单信息
		Map<String, Object> orderMap=travelOrderService.getOrderInfoByOrderType(map);
		String amount="";
		String prepayId="";
		if(null!=orderMap&&orderMap.size()>0){
		    if(orderMap.containsKey("amount")){
		        amount=orderMap.get("amount").toString();
		    }
		    if(orderMap.containsKey("prepayId")){
		        prepayId=orderMap.get("prepayId").toString();
            }
		}
		//获取微信支付会话id
		if("".equals(prepayId)){
		    Float totalMoney=Float.valueOf(amount);
		    totalMoney=totalMoney*100;
	        int totalFee=totalMoney.intValue();
	        String money=String.valueOf(totalFee);
	        String xmlStr=WeixinPayUtil.add(orderNumber,money,orderType); //获得会话ID
	        Map<String, Object> m=new HashMap<String, Object>();
	        Document doc = DocumentHelper.parseText(xmlStr);  
	        Element rootElement = doc.getRootElement();  
	        XmlToBean.ele2map(m,rootElement);
	        String str="";
	        if(m.containsKey("prepay_id")){
	            str=m.get("prepay_id").toString();
	            str=str.replace("{prepay_id=", "");
	            str=str.substring(0,str.length()-1);
	        }
	        prepayId=str;
	        map.put("prepayId", prepayId);
            travelOrderService.updateOrderInfoByType(map);
		}
		 //转成sortedMap,微信支付后台生成sign需要排序过的map
        SortedMap<String,Object> sort=new TreeMap<String,Object>();
	    String partnerid = sysparam.getStringParamByKey("c.wxpay.partnerid");
        //相关参数,可以定义一个Map做成动态的
	    sort.put("appid", sysparam.getStringParamByKey("c.wxpay.appid"));
	    sort.put("partnerid", partnerid);
	    sort.put("prepayid",prepayId);
	    sort.put("package", "Sign=WXPay");
	    String noncestr = RandomUtil.CreateRandom(32);
	    sort.put("noncestr", noncestr);
	    String timestamp = String.valueOf(System.currentTimeMillis());
	    timestamp = timestamp.substring(0,timestamp.length()-3);
	    sort.put("timestamp", timestamp);
	    String securit = sysparam.getStringParamByKey("c.wxpay.secret");
        //生成sign
        String sign=WeixinSignUtil.createSign("UTF-8", sort,securit);
        
        Map<String,Object> resultParam = new HashMap<String, Object>();
        resultParam.put("timestamp", timestamp);
        resultParam.put("noncestr", noncestr);
        resultParam.put("sign", sign);
        resultParam.put("prepayid", prepayId);
        return JsonUtil.Object2JsonSting(resultParam);
	}

这里需要注意的是

StringxmlStr=WeixinPayUtil.add(orderNumber,money,orderType); //获得会话ID

这个add方法即微信的下单接口,返回的xmlStr是xml格式的字符串,进行解析后,得出来perpayid入库。这里的money即金额,必须以分为单位!

依次参考下单接口:

0:线路订单 1:景点 2:酒店 3:商城 4:vip升级) 
public static String add(String orderNo,String TotalMoney,String orderType)
throws Exception { URL postUrl = new URL("https://api.mch.weixin.qq.com/pay/unifiedorder"); 
SysParamServiceImpl systemParam = (SysParamServiceImpl)SpringContextHolder.getBean(SysParamServiceImpl.class); 
HttpsURLConnection con = (HttpsURLConnection) postUrl.openConnection();//打开连接 con.setRequestMethod("POST");
//post方式提交 con.setDoOutput(true);
//打开读写属性,默认均为false con.setDoInput(true); con.setUseCaches(false);
//Post请求不能使用缓存 con.setInstanceFollowRedirects(true); 
DataOutputStream out = new DataOutputStream(con.getOutputStream()); 
Map<String, Object> vo = new HashMap<String, Object>(); 
//相关参数,可以定义一个Map做成动态的 
vo.put("appid", systemParam.getStringParamByKey("c.wxpay.appid")); 
vo.put("attach", "支付测试"); 
vo.put("body", "APP应用支付");
vo.put("mch_id", systemParam.getStringParamByKey("c.wxpay.partnerid")); 
vo.put("nonce_str", RandomUtil.CreateRandom(32)); 
String notifyUrl=systemParam.getStringParamByKey("sys.domain"); 
notifyUrl=notifyUrl+"/interface/wxpay/"+orderType; 
//调用微信下发通知的接口 vo.put("notify_url", notifyUrl); vo.put("out_trade_no", orderNo); vo.put("spbill_create_ip", "14.23.150.211"); 
vo.put("total_fee", TotalMoney); vo.put("trade_type", "APP"); //转成sortedMap,微信支付后台生成sign需要排序过的map 
SortedMap<String,Object> sort=new TreeMap<String,Object>(vo); 
String secrit = systemParam.getStringParamByKey("c.wxpay.secret"); 
//生成sign String sign=WeixinSignUtil.createSign("UTF-8", sort,secrit); 
//把sign放入map中 
vo.put("sign", sign);org.dom4j.Document doc = DocumentHelper.createDocument(); 
Element body = DocumentHelper.createElement("xml"); 
XmlUtil.buildMap2xmlBody(body,vo); 
doc.add(body); //发送请求 
out.writeUTF(doc.asXML()); 
System.out.println(doc.asXML()); 
out.flush(); out.close(); //接收数据 
BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8")); 
String line; StringBuffer responseText = new StringBuffer(); 
while ((line = reader.readLine()) != null) 
{ 
   responseText.append(line).append("\r\n"); } reader.close(); con.disconnect(); return responseText.toString()+""; 
 }

这里需要几个微信支付所需要的开发者账号信息,包括appid,微信支付商户号:partnerid,微信支付密码:

secret这些是商户申请微信app支付的信息提供给我们开发者,还有nonce_str参数需要配置我们自己定义的一个请求

该请求会在支付完成后,微信会主动根据这个请求来返回结果给我们。而且必须是外网,内网调不通

最后一步就是支付之后,微信会调用我们配置的nonce_str这个请求返回xml格式的结果给我们

@RequestMapping(value = "/interface/wxpay/{orderType}", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String getWeixinPayResult(HttpServletRequest request,
                                     HttpServletResponse response)
        throws IOException
    {
        try
        {
            String reqcontent = getRequestContent(request);
            interfaceLogger
                .info("################### ################# WeiXinPayResultInterface::getWeixinPayResult,request msg:"
                      + reqcontent);
            ResponseHandler resHandler = new ResponseHandler(request, response);
 
            // 创建请求对象
 
            // RequestHandler queryReq = new RequestHandler(request, response);
            String type = request.getParameter("orderType"); // 获取订单类型
 
            // queryReq.init();
            String securit = sysParam.getStringParamByKey("c.wxpay.secret");
            if (resHandler.getParameter("sign").equals(
                WeixinSignUtil.createSign("utf-8",
                    resHandler.getAllParameters(), securit)))
            {
 
                // 商户订单号
 
                String out_trade_no = resHandler.getParameter("out_trade_no");
                String totalFee = resHandler.getParameter("total_fee");
                System.out.println("out_trade_no:" + out_trade_no);
                Map<String, Object> map = new HashMap<String, Object>();
                String result_code = resHandler.getParameter("result_code");
                if (result_code.equals("SUCCESS"))
                {
                    // 新增到支付流水表
                    System.out
                        .println("########### ****************  totalFee1 #########:"
                                 + totalFee);
                    String serialno = RandomUtil.CreateRandom(32); // 生成支付流水
                    map.put("serialno", serialno);
                    map.put("totalFee", totalFee);
                    map.put("orderNumber", out_trade_no);
                    map.put("payWay", "2"); // 微信支付
                    if ("0" == type || "0".equals(type))
                    {// 路线订单
                        travelOrderService.addPayLog(map);
                        travelOrderService.updateOrderPayFlagAndSerialno(map); // 修改支付状态
                    }
                }
                else
                {
                    return resHandler.getParameter("err_code_des");
                }
                // 财付通订单号
 
                String transaction_id = resHandler
                    .getParameter("transaction_id");
 
                System.out.println("transaction_id:" + transaction_id);
 
                // 金额,以分为单位
 
                String total_fee = resHandler.getParameter("total_fee");
 
                // 如果有使用折扣券,discount有值,total_fee+discount=原请求的total_fee
 
                String discount = resHandler.getParameter("discount");
 
                System.out.println("----------------业务逻辑执行-----------------");
 
                // ——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
 
                System.out.println("----------------业务逻辑执行完毕-----------------");
 
                System.out.println("success"); // 请不要修改或删除
 
                System.out.println("即时到账支付成功");
 
                // 给财付通系统发送成功信息,财付通系统收到此结果后不再进行后续通知
 
                resHandler.sendToCFT("success");
 
                // 给微信服务器返回success 否则30分钟通知8次
                return "success";
 
            }
            else
            {
 
                System.out.println("通知签名验证失败");
 
                resHandler.sendToCFT("fail");
 
                response.setCharacterEncoding("utf-8");
                return "FAIL";
            }
        }
        catch (Exception e)
        {
            return "FAIL";
        }
 
    }

这是微信调用我们定义的请求来主动返回支付结果,但我们也可以写接口主动调用微信来获取订单信息
这里需要ios或者安卓调用我们java后台写的接口来获取支付结果:

?@RequestMapping(value = "/interface/wxpay/{orderType}", produces = "text/html;charset=UTF-8")
? ? @ResponseBody
? ? public String getWeixinPayResult(HttpServletRequest request,
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?HttpServletResponse response)
? ? ? ? throws IOException
? ? {
? ? ? ? try
? ? ? ? {
? ? ? ? ? ? String reqcontent = getRequestContent(request);
? ? ? ? ? ? interfaceLogger
? ? ? ? ? ? ? ? .info("################### ################# WeiXinPayResultInterface::getWeixinPayResult,request msg:"
? ? ? ? ? ? ? ? ? ? ? + reqcontent);
? ? ? ? ? ? ResponseHandler resHandler = new ResponseHandler(request, response);


? ? ? ? ? ? // 创建请求对象


? ? ? ? ? ? // RequestHandler queryReq = new RequestHandler(request, response);
? ? ? ? ? ? String type = request.getParameter("orderType"); // 获取订单类型


? ? ? ? ? ? // queryReq.init();
? ? ? ? ? ? String securit = sysParam.getStringParamByKey("c.wxpay.secret");
? ? ? ? ? ? if (resHandler.getParameter("sign").equals(
? ? ? ? ? ? ? ? WeixinSignUtil.createSign("utf-8",
? ? ? ? ? ? ? ? ? ? resHandler.getAllParameters(), securit)))
? ? ? ? ? ? {


? ? ? ? ? ? ? ? // 商户订单号


? ? ? ? ? ? ? ? String out_trade_no = resHandler.getParameter("out_trade_no");
? ? ? ? ? ? ? ? String totalFee = resHandler.getParameter("total_fee");
? ? ? ? ? ? ? ? System.out.println("out_trade_no:" + out_trade_no);
? ? ? ? ? ? ? ? Map<String, Object> map = new HashMap<String, Object>();
? ? ? ? ? ? ? ? String result_code = resHandler.getParameter("result_code");
? ? ? ? ? ? ? ? if (result_code.equals("SUCCESS"))
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? // 新增到支付流水表
? ? ? ? ? ? ? ? ? ? System.out
? ? ? ? ? ? ? ? ? ? ? ? .println("########### **************** ?totalFee1 #########:"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?+ totalFee);
? ? ? ? ? ? ? ? ? ? String serialno = RandomUtil.CreateRandom(32); // 生成支付流水
? ? ? ? ? ? ? ? ? ? map.put("serialno", serialno);
? ? ? ? ? ? ? ? ? ? map.put("totalFee", totalFee);
? ? ? ? ? ? ? ? ? ? map.put("orderNumber", out_trade_no);
? ? ? ? ? ? ? ? ? ? map.put("payWay", "2"); // 微信支付
? ? ? ? ? ? ? ? ? ? if ("0" == type || "0".equals(type))
? ? ? ? ? ? ? ? ? ? {// 路线订单
? ? ? ? ? ? ? ? ? ? ? ? travelOrderService.addPayLog(map);
? ? ? ? ? ? ? ? ? ? ? ? travelOrderService.updateOrderPayFlagAndSerialno(map); // 修改支付状态
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? else
? ? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? return resHandler.getParameter("err_code_des");
? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? // 财付通订单号


? ? ? ? ? ? ? ? String transaction_id = resHandler
? ? ? ? ? ? ? ? ? ? .getParameter("transaction_id");


? ? ? ? ? ? ? ? System.out.println("transaction_id:" + transaction_id);


? ? ? ? ? ? ? ? // 金额,以分为单位


? ? ? ? ? ? ? ? String total_fee = resHandler.getParameter("total_fee");


? ? ? ? ? ? ? ? // 如果有使用折扣券,discount有值,total_fee+discount=原请求的total_fee


? ? ? ? ? ? ? ? String discount = resHandler.getParameter("discount");


? ? ? ? ? ? ? ? System.out.println("----------------业务逻辑执行-----------------");


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


? ? ? ? ? ? ? ? System.out.println("----------------业务逻辑执行完毕-----------------");


? ? ? ? ? ? ? ? System.out.println("success"); // 请不要修改或删除


? ? ? ? ? ? ? ? System.out.println("即时到账支付成功");


? ? ? ? ? ? ? ? // 给财付通系统发送成功信息,财付通系统收到此结果后不再进行后续通知


? ? ? ? ? ? ? ? resHandler.sendToCFT("success");


? ? ? ? ? ? ? ? // 给微信服务器返回success 否则30分钟通知8次
? ? ? ? ? ? ? ? return "success";


? ? ? ? ? ? }
? ? ? ? ? ? else
? ? ? ? ? ? {


? ? ? ? ? ? ? ? System.out.println("通知签名验证失败");


? ? ? ? ? ? ? ? resHandler.sendToCFT("fail");


? ? ? ? ? ? ? ? response.setCharacterEncoding("utf-8");
? ? ? ? ? ? ? ? return "FAIL";
? ? ? ? ? ? }
? ? ? ? }
? ? ? ? catch (Exception e)
? ? ? ? {
? ? ? ? ? ? return "FAIL";
? ? ? ? }


? ? }
/**
     * 4.22客户端微信支付成功后查询后台支付结果接口
     * 
     * @param req
     * @param rsp
     * @return String 返回json字符串 如果有违例,请使用@exception/throws [违例类型]
     *         [违例说明:异常的注释必须说明该异常的含义及什么条件下抛出该
     * @throws Exception
     * @see [类、类#方法、类#成员]
     */
    @RequestMapping(value = "/interface/payStatus", method = RequestMethod.POST, produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String getPayStatus(HttpServletRequest req, HttpServletResponse rsp)
        throws Exception
    {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        try
        {
            URL postUrl = new URL(
                "https://api.mch.weixin.qq.com/pay/orderquery");
            // 获取请求内容
            String requestContent = getRequestContent(req);
            // 日志
            interfaceLogger.info("request payStatus:" + requestContent);
            // 解析参数
            requestParam = parseAndCheckParam(requestContent, resultMap,
                requestParam, systemParam.getSystemKey());
            // 校验参数
            checkStatusParam(resultMap);
            // 校验token及获取用户信息
            Map<String, Object> userInfo = checkTokenAndGetUserInfo(
                tokenService, appuserManager, requestParam, resultMap);
 
            String user_id = (String)userInfo.get("userId");
            String totalFee = (String)requestParam.get("totalFee");
            String type = (String)requestParam.get("orderType"); // 获取订单类型参数
            if (null == user_id)
            {
                resultMap.put("resultCode",
                    ErrorCodeConstants.INVALID_TOKEN_ERROR);
            }
            SysParamServiceImpl sysParam = (SysParamServiceImpl)SpringContextHolder
                .getBean(SysParamServiceImpl.class);
            HttpsURLConnection con = (HttpsURLConnection)postUrl
                .openConnection();// 打开连接
            con.setRequestMethod("POST");// post方式提交
            con.setDoOutput(true);// 打开读写属性,默认均为false
            con.setDoInput(true);
            con.setUseCaches(false);// Post请求不能使用缓存
            con.setInstanceFollowRedirects(true);
            // DataOutputStream out = new
            // DataOutputStream(con.getOutputStream());
            PrintWriter out = new PrintWriter(con.getOutputStream());
            Map<String, Object> map = new HashMap<String, Object>();
            // 相关参数,可以定义一个Map做成动态的
            map.put("appid", sysParam.getStringParamByKey("c.wxpay.appid")); // appID
            map.put("mch_id", sysParam.getStringParamByKey("c.wxpay.partnerid")); // 商户号
            map.put("nonce_str", RandomUtil.CreateRandom(32)); // 随机数
            String orderId = requestParam.get("outTradeNo").toString();
            map.put("out_trade_no", orderId); // 订单号
            // String mo="3000";
            // insertMoneyAccounting(orderId,mo); //利润分配
            // 转成sortedMap,微信支付后台生成sign需要排序过的map
            SortedMap<String, Object> sort = new TreeMap<String, Object>(map);
            String secrit = sysParam.getStringParamByKey("c.wxpay.secret");
            // 生成sign
            String sign = WeixinSignUtil.createSign("UTF-8", sort, secrit);
            // 把sign放入map中
            map.put("sign", sign); // 签名
            Document doc = DocumentHelper.createDocument();
            Element body = DocumentHelper.createElement("xml");
            buildMap2xmlBody(body, map);
            doc.add(body);
            // 发送请求
            // out.writeUTF(doc.asXML());
            String outStr = doc.asXML();
            out.print(outStr);
            System.out.println(doc.asXML());
            out.flush();
            out.close();
            // 接收数据
            BufferedReader reader = new BufferedReader(new InputStreamReader(
                con.getInputStream(), "UTF-8"));
            String line;
            StringBuffer responseText = new StringBuffer();
            while ( (line = reader.readLine()) != null)
            {
                responseText.append(line).append("\r\n");
            }
            reader.close();
            con.disconnect();
            String resXml = responseText.toString() + ""; // 获取从微信付款的结果
                                                          // ,以String类型的xml格式返回
            System.out.println("result:" + resXml);
            // 解析xml
            Map<String, Object> m = new HashMap<String, Object>();
            Document d = DocumentHelper.parseText(resXml);
            Element rootElement = d.getRootElement();
            XmlToBean.ele2map(m, rootElement);
            String str = "";
            if (m.containsKey("trade_state"))
            {
                str = m.get("trade_state").toString();
                str = str.replace("{trade_state=", "");
                str = str.substring(0, str.length() - 1);
                if ("SUCCESS" == str || "SUCCESS".equals(str))
                {
                    ?if ("0".equals(type)) { ?
? ? ? ? ? ? ? ? ? ? ? ? //支付成功后操作... ?
? ? ? ? ? ? ? ? ? ? } ?
                }
                else if ("REFUND" == str || "REFUND".equals(str))
                {
                    str = "1"; // 转入退款
                }
                else if ("NOTPAY" == str || "NOTPAY".equals(str))
                {
                    str = "2"; // 未支付
                }
                else if ("CLOSED" == str || "CLOSED".equals(str))
                {
                    str = "3"; // 已关闭
                }
                else if ("REVOKED" == str || "REVOKED".equals(str))
                {
                    str = "4"; // 已撤销
                }
                else if ("USERPAYING" == str || "USERPAYING".equals(str))
                {
                    str = "5"; // 用户支付中
                }
                else if ("PAYERROR" == str || "PAYERROR".equals(str))
                {
                    str = "6"; // 支付失败
                }
                resultMap.put("status", str);
                resultMap.put("resultCode",
                    ErrorCodeConstants.RESULT_CODE_SUCCESS);
            }
        }
        catch (Exception e)
        {
            logger.error("loginOut:system exception!", e);
            resultMap.clear();
            resultMap.put("resultCode", ErrorCodeConstants.SYSTEM_ERROR);
        }
        interfaceLogger.info("response payStatus:" + resultMap.toString());
        return JsonUtil.Object2EncodeJsonSting(resultMap,
            systemParam.getSystemKey());
    }

requestParam.get("XXX"),XXX是客户端调用我们(java服务器端)接口给我们传的参数,需要给我们totalFee(金额),orderType(订单类型)等然后我们返回支付结果给客户端

二、支付宝支付:支付宝支付流程上和微信支付稍微有所差别,支付宝不需要调用下单结果,但是也需要一个类似于微信prepayId的字段来入库,作用上跟prepayId差不多,名称可以自己定义,我这边暂时为aliPayInfo:首先看jsp页面的js代码:


//选择支付宝,立即支付 
			function aliPay(outTradeNo){
				var orderType="0";
				var info = $("#aliPayInfo").val();//订单信息 
				var totalAmount = $("#moeny").val();//总金额
				var orderName = $("#orderName").val();//订单名称
				
				//type 0:线路 1:景点  2:酒店 3:商城 4:VIP
				var prams = {
						aliPayInfo : info,
						type : orderType,
						orderNumber : outTradeNo,
						money : totalAmount,
						orderName : orderName
				};
				//先调支付宝确定是否下单 否则返回支付宝会话信息
				$.ajax({
	                url : '<%=basePath%>client/hotel/foundZFBOrder.do',
	                type : "post",
	                data : prams,
	                cache : false,
	                dataType : "json",
	                success : function(data)
	                {
	                	//alert("info +===="+data.info);
	                	if(data.isSuccess){
			    			if(isAndroid){
			    				ClientInterface.aliPay(data.info,outTradeNo,orderType,totalAmount);
			    			}else if(isiOS){
			    				window.location.href='http://localhost/aliPay/'+data.info+';'+outTradeNo+";"+orderType+";"+totalAmount;
			    			}
	                	}else{
	                		var title = "支付宝下单失败";
							prompt(title);
	                	}
	                }, 
	                error : function(data){
	                	var title = "支付宝下单失败";
						prompt(title);
	                }
		 		});
			}

页面上的aliPayInfo可以为空,因为第一次去调用支付宝时这个为空,如果不支付,但是还是入库了,需要去数据库里查一下,那么共用这个页面的话aliPayInfo就不为空
然后去后台写这个ajax请求:


@RequestMapping(value="/foundZFBOrder", produces = "application/json;charset=UTF-8")
    @ResponseBody
    public Map<String, Object> foundZFBOrder(HttpServletRequest request){
        //支付宝信息
        String aliPayInfo = request.getParameter("aliPayInfo");
        //金额
        String money = request.getParameter("money");
        //订单名称
        String orderName = request.getParameter("orderName");
        //订单编号
        String orderNumber = request.getParameter("orderNumber");
        //订单类型(0:线路 1:景点  2:酒店 3:商城 4:VIP)
        String type = request.getParameter("type");
        
        boolean isSuccess = false;
        
        //判断是否生成过支付宝信息
        if(StringUtils.isBlank(aliPayInfo)){
           
            //生成支付宝信息
            aliPayInfo = AliPayUtil.orderInfo(money, orderName, orderNumber, type);
            
            //修改表中支付宝信息
            if(StringUtils.isNotBlank(aliPayInfo)){
                isSuccess = true;
                Map<String, Object> map = new HashMap<String, Object>();
                map.put("aliPayInfo", aliPayInfo);
                map.put("type", type);
                map.put("orderNumber", orderNumber);
                try {
                    travelOrderService.updateOrderInfoByType(map);
                }
                catch (Exception e) {
                    e.printStackTrace();
                }
            }
            
            /** 打印支付宝响应日志  */
            if (interfaceLogger.isInfoEnabled()) {
                interfaceLogger.info("[HotelController][foundZFBOrder]ZFB " + table + " result :["
                                     + JSON.toJSONString(aliPayInfo) + "]");
            }
        }
        
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("info", aliPayInfo);
        map.put("isSuccess", isSuccess);
        return map;
    }

这里的 aliPayInfo = AliPayUtil.orderInfo(money, orderName, orderNumber, type);

类似于微信的下单接口(aliPayInfo 需要入库),但不是下单接口,因为支付宝支付没有下单接口,详情可以查看支付宝支付文档

下面继续写orderInfo方法:

/**
	 * 
	 * @param amount 订单金额
	 * @param subject 订单标题
	 * @param body 订单描述
	 * @param outTradeNo订单号
	 * @return
	 */
	public static String orderInfo(String amount,String subject,String outTradeNo,String type) {
		//获取appid
		String appId=Const.APPID;
		Map<String, String> authInfoMap = OrderInfoUtil.buildOrderParamMap(appId,amount,subject,outTradeNo,type);
		String info = OrderInfoUtil.buildOrderParam(authInfoMap);
		String rsaPrivate =Const.RSAPRIVATE; //获取商户密钥
		String sign = OrderInfoUtil.getSign(authInfoMap, rsaPrivate);
		final String orderInfo = info + "&" + sign;
		return orderInfo;
  }

这里和微信一样需要支付宝商户的appid和RSAPRIVATE提供给我们开发者,
然后编写支付宝支付工具类:

public class OrderInfoUtil {
	
	/**
	 * 构造授权参数列表
	 * 
	 * @param pid
	 * @param app_id
	 * @param target_id
	 * @return
	 */
	public static Map<String, String> buildAuthInfoMap(String pid, String app_id, String target_id) {
		Map<String, String> keyValues = new HashMap<String, String>();
 
		// 商户签约拿到的app_id,如:2013081700024223
		keyValues.put("app_id", app_id);
 
		// 商户签约拿到的pid,如:2088102123816631
		keyValues.put("pid", pid);
 
		// 服务接口名称, 固定值
		keyValues.put("apiname", "com.alipay.account.auth");
 
		// 商户类型标识, 固定值
		keyValues.put("app_name", "mc");
 
		// 业务类型, 固定值
		keyValues.put("biz_type", "openservice");
 
		// 产品码, 固定值
		keyValues.put("product_id", "APP_FAST_LOGIN");
 
		// 授权范围, 固定值
		keyValues.put("scope", "kuaijie");
 
		// 商户唯一标识,如:kkkkk091125
		keyValues.put("target_id", target_id);
 
		// 授权类型, 固定值
		keyValues.put("auth_type", "AUTHACCOUNT");
 
		// 签名类型
		keyValues.put("sign_type", "RSA");
 
		return keyValues;
	}
 
	/**
	 * 构造支付订单参数列表
	 * @param pid
	 * @param app_id
	 * @param target_id
	 * @return
	 */
	public static Map<String, String> buildOrderParamMap(String appId,String amount,String subject,String outTradeNo,String type) {
		Map<String, String> keyValues = new HashMap<String, String>();
 
		keyValues.put("app_id", appId);
 
		keyValues.put("biz_content", "{\"timeout_express\":\"30m\",\"product_code\":\"QUICK_MSECURITY_PAY\",\"total_amount\":\""+amount+"\",\"subject\":\""+subject+"\",\"out_trade_no\":\"" +outTradeNo +  "\"}");
		
		keyValues.put("charset", "utf-8");
 
		keyValues.put("method", "alipay.trade.app.pay");
 
		keyValues.put("sign_type", "RSA");
		//获取域名 
		SysParamServiceImpl systemParam = (SysParamServiceImpl)SpringContextHolder.getBean(SysParamServiceImpl.class);
		//String notifyUrl="http://180.96.11.10:8080/tourism";
		String notifyUrl=systemParam.getStringParamByKey("sys.domain");
		
		notifyUrl=notifyUrl+"/interface/alipay/"+type;
		
		keyValues.put("notify_url", notifyUrl);
		
		String timestamp = "";
	    Date date=new Date();
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //设置时间格式
		timestamp=sdf.format(date);
	    keyValues.put("timestamp", timestamp);
	    keyValues.put("version", "1.0");
		return keyValues;
	}
	
	/**
	 * 构造支付订单参数信息
	 * 
	 * @param map
	 * 支付订单参数
	 * @return
	 */
	public static String buildOrderParam(Map<String, String> map) {
		List<String> keys = new ArrayList<String>(map.keySet());
 
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < keys.size() - 1; i++) {
			String key = keys.get(i);
			String value = map.get(key);
			sb.append(buildKeyValue(key, value, true));
			sb.append("&");
		}
 
		String tailKey = keys.get(keys.size() - 1);
		String tailValue = map.get(tailKey);
		sb.append(buildKeyValue(tailKey, tailValue, true));
 
		return sb.toString();
	}
	
	/**
	 * 拼接键值对
	 * 
	 * @param key
	 * @param value
	 * @param isEncode
	 * @return
	 */
	private static String buildKeyValue(String key, String value, boolean isEncode) {
		StringBuilder sb = new StringBuilder();
		sb.append(key);
		sb.append("=");
		if (isEncode) {
			try {
				sb.append(URLEncoder.encode(value, "UTF-8"));
			} catch (UnsupportedEncodingException e) {
				sb.append(value);
			}
		} else {
			sb.append(value);
		}
		return sb.toString();
	}
	
	/**
	 * 对支付参数信息进行签名
	 * 
	 * @param map
	 *            待签名授权信息
	 * 
	 * @return
	 */
	public static String getSign(Map<String, String> map, String rsaKey) {
		List<String> keys = new ArrayList<String>(map.keySet());
		// key排序
		Collections.sort(keys);
 
		StringBuilder authInfo = new StringBuilder();
		for (int i = 0; i < keys.size() - 1; i++) {
			String key = keys.get(i);
			String value = map.get(key).toString();
			authInfo.append(buildKeyValue(key, value, false));
			authInfo.append("&");
		}
 
		String tailKey = keys.get(keys.size() - 1);
		String tailValue =map.get(tailKey).toString();
		authInfo.append(buildKeyValue(tailKey, tailValue, false));
 
		String oriSign = SignUtils.sign(authInfo.toString(), rsaKey);
		String encodedSign = "";
 
		try {
			encodedSign = URLEncoder.encode(oriSign, "UTF-8");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return "sign=" + encodedSign;
	}
	
	/**
	 * 要求外部订单号必须唯一。
	 * @return
	 */
	private static String getOutTradeNo() {
		SimpleDateFormat format = new SimpleDateFormat("MMddHHmmss", Locale.getDefault());
		Date date = new Date();
		String key = format.format(date);
 
		Random r = new Random();
		key = key + r.nextInt();
		key = key.substring(0, 15);
		return key;
	}
 
}

keyValues.put("notify_url", notifyUrl);这个和微信一样,需要设置一个供支付宝支付后返回给我们的支付结果通知的请求,需自己定义,可带参数,必须在外网下才能调用
最后根据我们定义的请求,来写接收支付宝返回给我们的结果:

@RequestMapping(value = "/interface/alipay/{type}", produces = "text/html;charset=UTF-8")
    @ResponseBody
    public String getzfbPayResult(HttpServletRequest request,HttpServletResponse response){
    	try{
    		String reqcontent = getRequestContent(request);
    		interfaceLogger.info("################### ################# WeiXinPayResultInterface::alipay,request msg:"+reqcontent);
    		//解析url
    		//reqcontent=stringFarmat(reqcontent); 
    		 try {
    			 reqcontent= URLDecoder.decode(reqcontent, "UTF-8");
    				} catch (UnsupportedEncodingException e) {
    					e.printStackTrace();
    				}
    		interfaceLogger.info("###########获取参数解析url:$@@@@@@@@@@@@@@@@@@@@@@@@@========="+reqcontent);
    		//转换为map
    		Map<String, String> paramMap=stringtoArray(reqcontent);
    		//获取orderType
    		String orderType=request.getRequestURI();
    		int i=orderType.lastIndexOf("/");
    		orderType=orderType.substring(i+1, orderType.length()); 
    		//验证签名
    		//支付宝公钥
    		String publicKey=Const.PUBLICKEY; //支付宝公钥
    		 //字符集
    		String charsetType="UTF-8";
    		//验证签名
	    	boolean signVerified = AlipaySignature.rsaCheckV1(paramMap, publicKey, charsetType); //调用SDK验证签名
	    		interfaceLogger.info("###########验证签名结果:$@@@@@@@@@@@@@@@@@@@@@@@@@========="+signVerified);
	    		if(signVerified){
	    				//验证金额订单号
	    			interfaceLogger.info("*****************验证签名成功:&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
	    			if(paramMap.containsKey("trade_status")){
	    				String resultStr=paramMap.get("trade_status");
	    				if(resultStr.equals("TRADE_SUCCESS")||resultStr.equals("TRADE_FINISHED")){
	    					//支付成功后操作...
	    			}
	    			return "success";
	    		}else{
	    			interfaceLogger.info("&&&&&&&&&&&&&&&&验证签名失败:***************************");
	               return "failure";	
	    		}
    		
    	}catch (Exception e){
    		interfaceLogger.info("###########待签名字符串str:$@@@@@@@@@@@@@@@@@@@@@@@@@=========",e);
			e.printStackTrace();
			return "failure";
		}
    }

Tags:

最近发表
标签列表