欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

支付宝支付

程序员文章站 2022-04-11 13:49:03
...

1、实名注册登录https://openhome.alipay.com

2、开发者中心->开发服务->研发服务->沙箱应用

支付宝支付

3、设置应用公钥

下载工具(鼠标移动到RSA2(SHA256)**(推荐)后面的!上,有工具下载的提示,点击下载)

解压后运行《RSA签名验签工具.bat》选择2048,生成**

上传应用公钥,生成支付宝公钥

目前为止有3个**(成对的应用公钥和私钥 、支付宝公钥)

4、SDK和DEMO下载  https://docs.open.alipay.com/54/103419/

就是这2货

alipay-sdk-java-3.1.0.jar  (将包导入工程)

alipay.trade.wap.pay-java-utf-8

5 、创建一个配置类AlipayConfig

package com.alipay.config;

public class AlipayConfig {
	public class AliPayConfig {
    // 商户appid
    private  String appid;
    // 私钥 pkcs8格式的
    private  String rsaPrivateKey;
    // 服务器异步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
    private  String notifyUrl;
    // 页面跳转同步通知页面路径 需http://或者https://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 商户可以自定义同步跳转地址
    private  String returnUrl;
    // 请求网关地址
    private  String url;
    // 编码
    private  String charset = "UTF-8";
    // 返回格式
    private  String format = "json";
    // 支付宝公钥
    private  String alipayPublicKey;
    // 日志记录目录
    private  String logPath = "/log";
    // RSA2
    private  String signType = "RSA2";
    // 支付成功跳转页
    private String paymentSuccessUrl;
    //支付失败跳转页面
    private String paymentFailUrl;

}

6 、spring注入,spring配置文件根据实际配置

<!--alipay相关配置-->
    <bean class="cn.itrip.trade.config.AlipayConfig">
        <property name="appid" value="注册沙箱"/>
        <property name="alipayPublicKey" value="按自己生成的"/>
        <property name="url" value="https://openapi.alipaydev.com/gateway.do"/>
        <property name="charset" value="UTF-8"/>
        <property name="format" value="json"/>
        <property name="logPath" value="/logs"/>
        <property name="notifyUrl" value="/XXXXX/notify"/>
        <property name="paymentFailUrl" value="/XXXXX/fail.jsp"/>
        <property name="paymentSuccessUrl" value="/XXXXX/success.jsp"/>
        <property name="returnUrl" value="/XXXXX/return"/>
        <property name="rsaPrivateKey" value="按自己生成的"/>
        <property name="signType" value="RSA2"/>
    </bean>

7  项目实现

核心api 

AlipayClient : 封装签名和验证

AlipayTradeWapPayModel : 支付请求类

AlipayTradeWapPayRequest : 封装支付信息类

逻辑顺序  商户订单id->订单信息(页面显示,同时绑定相关数据)->确认订单提交给支付宝支付->支付宝支付返回回调信息(notify和return)

service方法获取订单

显示订单信息 , 该页面支付宝有模板 , 根据订单信息修改

\alipay.trade.wap.pay-java-utf-8\alipay.trade.wap.pay-java-utf-8\WebContent\wappay在此路径下的pay.jsp文件中有模板

<div id="main">
    <form name=alipayment action='../pay' method=post>
        <div id="body" style="clear:left">
            <dl class="content">
                <dt>商户订单号:</dt>
                <dd>
                    ${orderNo}
                    <input hidden="hidden" id="WIDout_trade_no" name="WIDout_trade_no" value="${orderNo}" />必填 订单id
                    <input hidden="hidden" id="WIDsubject" name="WIDsubject" value="${hotelName}"/>必填 订单名称
                    <input hidden="hidden" id="WIDtotal_amount" name="WIDtotal_amount" value="${payAmount}"/>必填 订单金额
                    <input hidden="hidden" id="WIDbody" name="WIDbody" />选填
                </dd>
                <hr class="one_line">
                <dt>订单名称:</dt>
                <dd>
                    ${hotelName}
                </dd>
                <hr class="one_line">
                <dt>付款金额:</dt>
                <dd>
                    ${payAmount}
                </dd>
                <hr class="one_line"/>
                <dt>商品描述:</dt>
                <dd>
                    房间号:${roomId};房间数:${count};入住天数:${bookingDays}
                </dd>
                <hr class="one_line">
                <dt></dt>
                <dd id="btn-dd">
                        <span class="new-btn-login-sp">
                            <button class="new-btn-login" type="submit" style="text-align:center;">确 认</button>
                        </span>
                    <span class="note-help">如果您点击“确认”按钮,即表示您同意该次的执行操作。</span>
                </dd>
            </dl>
        </div>
    </form>
    <div id="foot">
        <ul class="foot-ul">
            <li>
                支付宝版权所有 2015-2018 ALIPAY.COM
            </li>
        </ul>
    </div>
</div>

根据订单信息,确认提交controller的pay方法 , 该方法的实现由代码模板

\alipay.trade.wap.pay-java-utf-8\alipay.trade.wap.pay-java-utf-8\WebContent\wappay在此路径下的pay.jsp文件中有模板

//2.点击订单页面提交,订单提交支付宝
	@ApiOperation(value = "支付宝支付")
	@RequestMapping(value = "/pay",method = RequestMethod.POST)
	public void pay(@ApiParam @RequestParam String WIDout_trade_no, @ApiParam @RequestParam String WIDsubject,
	                @ApiParam @RequestParam String WIDtotal_amount, HttpServletResponse response){
		// 超时时间 可空
		String timeout_express="2m";
		// 销售产品码 必填
		String product_code="QUICK_WAP_WAY";
		/**********************/
		// SDK 公共请求类,包含公共请求参数,以及封装了签名与验签,开发者无需关注签名与验签
		//调用RSA签名方式
		AlipayClient client = new DefaultAlipayClient(alipayConfig.getUrl(), alipayConfig.getAppid(),
				alipayConfig.getRsaPrivateKey(), alipayConfig.getFormat(),
				alipayConfig.getCharset(), alipayConfig.getAlipayPublicKey(),alipayConfig.getSignType());
		AlipayTradeWapPayRequest alipay_request=new AlipayTradeWapPayRequest();

		// 封装请求支付信息
		AlipayTradeWapPayModel model=new AlipayTradeWapPayModel();
		model.setOutTradeNo(WIDout_trade_no);
		model.setSubject(WIDsubject);
		model.setTotalAmount(WIDtotal_amount);
		model.setTimeoutExpress(timeout_express);
		model.setProductCode(product_code);
		alipay_request.setBizModel(model);
		// 设置异步通知地址
		alipay_request.setNotifyUrl(alipayConfig.getNotifyUrl());
		// 设置同步地址
		alipay_request.setReturnUrl(alipayConfig.getReturnUrl());

		// form表单生产
		String form = "";
		try {
			// 调用SDK生成表单
			form = client.pageExecute(alipay_request).getBody();
			response.setContentType("text/html;charset=" + alipayConfig.getCharset());
			response.getWriter().write(form);//直接将完整的表单html输出到页面
			response.getWriter().flush();
			response.getWriter().close();
		} catch (AlipayApiException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}  catch (IOException e) {
			e.printStackTrace();
		}

	}
支付后回调方法notify(回调给商户 , 验证成功可以对订单更新 , 库存更新)和return(回调给买家 , 告诉买家是否支付成功等信息)

notify方法有模板

\alipay.trade.wap.pay-java-utf-8\alipay.trade.wap.pay-java-utf-8\WebContent目录下的notify.jsp

//3.notify
	@ApiOperation(value = "支付宝回调方法,通知商户")
	@RequestMapping(value = "/notify",method = RequestMethod.GET)
	public void payNotify(HttpServletRequest request, HttpServletResponse response){
		//获取支付宝POST过来反馈信息
		Map<String,String> params = new HashMap<String,String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "gbk");
			params.put(name, valueStr);
		}
		//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
		try {
			//商户订单号

			String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
			//支付宝交易号

			String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");

			//交易状态
			String trade_status = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
			//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
			//计算得出通知验证结果
			//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
			boolean verify_result = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(),alipayConfig.getCharset(), "RSA2");
		if(verify_result){//验证成功
			//////////////////////////////////////////////////////////////////////////////////////////
			//请在这里加上商户的业务逻辑程序代码

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

			if(trade_status.equals("TRADE_FINISHED")){
				//判断该笔订单是否在商户网站中已经做过处理
				//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
				//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
				//如果有做过处理,不执行商户的业务程序
				orderService.paySuccess(out_trade_no,1,trade_no);
				//注意:
				//如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
				//如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
			} else if (trade_status.equals("TRADE_SUCCESS")){
				//判断该笔订单是否在商户网站中已经做过处理
				//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,并执行商户的业务程序
				//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
				//如果有做过处理,不执行商户的业务程序
				orderService.paySuccess(out_trade_no,1,trade_no);
				//注意:
				//如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
			}

			//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——
			response.getWriter().println("success");	//请不要修改或删除

			//////////////////////////////////////////////////////////////////////////////////////////
		}else{//验证失败
			orderService.payFail(out_trade_no,1,trade_no);
			response.getWriter().println("fail");
		}
		}  catch (AlipayApiException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

return方法

//4.return
	@ApiOperation(value = "支付宝回调方法,页面返回,返回给用户")
	@RequestMapping(value = "/return",method = RequestMethod.GET)
	public void payReturn(HttpServletRequest request, HttpServletResponse response) {
		try {
		//获取支付宝GET过来反馈信息
		Map<String, String> params = new HashMap<String, String>();
		Map requestParams = request.getParameterMap();
		for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i]
						: valueStr + values[i] + ",";
			}
			//乱码解决,这段代码在出现乱码时使用。如果mysign和sign不相等也可以使用这段代码转化
			valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
			params.put(name, valueStr);
		}

		//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
		//商户订单号

		String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"), "UTF-8");

		//支付宝交易号

		String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"), "UTF-8");

		//获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
		//计算得出通知验证结果
		//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
		boolean verify_result = AlipaySignature.rsaCheckV1(params, alipayConfig.getAlipayPublicKey(), alipayConfig.getCharset(), "RSA2");

		if (verify_result) {//验证成功
			//////////////////////////////////////////////////////////////////////////////////////////
			//请在这里加上商户的业务逻辑程序代码
			//该页面可做页面美工编辑
			response.sendRedirect("../jsp/success.jsp");
			//——请根据您的业务逻辑来编写程序(以上代码仅作参考)——

			//////////////////////////////////////////////////////////////////////////////////////////
		} else {
			//该页面可做页面美工编辑
			response.sendRedirect("../jsp/fail.jsp");
		}
		} catch (AlipayApiException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

 

总结步骤 : 

1 注册账号 , 获取**3个

2  SDK和DEMO下载

3 .导包

4 . 编写一个AlipayConfig.java类

5 . spring注入该类

6 . 获取订单信息 , 绑定数据到订单页面(页面由支付宝提供模板)

7 . 确认订单支付 ,controller中编写pay方法,

8 . 回调方法notify和return