JAVA PC端扫码支付(二)支付宝支付开发

一、配置

配置

  1. 用户注册

    首先用公司相关信息在蚂蚁金服开放平台注册一个支付宝账户(https://openhome.alipay.com/platform/home.htm) 注册公司支付宝账号

    然后在进入开放平台后进入开发者中心>网页&移动应用接入中

    输入图片说明

    接着和支付宝签约,接入支付功能(手机网站支付)

    输入图片说明

  2. 配置和获取相关开发信息

    进入申请的支付功能页面,配置授权回调地址和密钥

    输入图片说明

ok,现在我们获取了APPID、支付宝网关、授权回调地址、商户私钥、应用公钥、支付宝公钥等相关信息,开发时我将会把他们写到配置文件中

另外,我们还需要一个支付宝的SDK,请大家自行下载

输入图片说明到此,所需的全部准备工作完成,大家可以愉快的开发了

二、开发

支付逻辑

  • 支付逻辑

    1. 商户系统调用支付宝预下单接口alipay.trade.precreate,获得该订单二维码图片地址。
    2. 发起轮询获得支付结果:等待5秒后调用交易查询接口alipay.trade.query通过支付时传入的商户订单号(out_trade_no)查询支付结果(返回参数TRADE_STATUS),如果仍然返回等待用户付款(WAIT_BUYER_PAY),则再次等待5秒后继续查询,直到返回确切的支付结果(成功TRADE_SUCCESS 或 已撤销关闭TRADE_CLOSED),或是超出轮询时间。在最后一次查询仍然返回等待用户付款的情况下,必须立即调用交易撤销接口alipay.trade.cancel将这笔交易撤销,避免用户继续支付。
    3. 这里是列表文本除了主动轮询,也可以通过接受异步通知获得支付结果。
    4. 和微信支付差异的地方就在支付宝返回查询用户付款状态的方式,支付宝除了主动轮询查询支付状态,还可以异步获取。在项目里我们将这两种方式交叉使用。

公共请求参数

  • 公共请求参数

    输入图片说明

与支付无关的业务逻辑

  • 与支付无关的业务逻辑

    这部分代码已经在上篇文章微信支付中贴出,这里就不再重新贴一遍了

封装固定参数

  • 封装固定参数
package com.andata.conf;
/* * 
 *类名:AlipayConfig
 *功能:基础配置类
 *详细:设置帐户有关信息及返回路径
 *提示:如何获取安全校验码和合作身份者ID
 *1.用您的签约支付宝账号登录支付宝网站(www.alipay.com)
 *2.点击“商家服务”(https://b.alipay.com/order/myOrder.htm)
 *3.点击“查询合作者身份(PID)”、“查询安全校验码(Key)”
 *安全校验码查看时,输入支付密码后,页面呈灰色的现象,怎么办?
 *解决方法:
 *1、检查浏览器配置,不让浏览器做弹框屏蔽设置
 *2、更换浏览器或电脑,重新登录查询。
 */
public class AlipayConfig {
	//ServiceURL
	public static String ServiceUrl="https://openapi.alipay.com/gateway.do";
	//APP支付宝支付业务:app_id
	public static String app_id = "20180xxxxxxxxxxxxxx";
	// 商户的私钥,使用支付宝自带的openssl工具生成。
	public static String private_key = "xxxxxxxxxxxxxxxxxxx";
	// 应用的公钥,无需修改该值
	public static String ali_public_key  = "xxxxxxxxxxxxxxxxxxxxx";
	// 支付宝的公钥,去open.alipay.com对应应用下查看。
	public static String zfb_public_key  = "xxxxxxxxxxxxxxxxxxxxx";
	// 字符编码格式 目前支持 gbk 或 utf-8
	public static String input_charset = "UTF-8";
}

AliPayController

package com.andata.controller;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradeCancelRequest;
import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeQueryRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.andata.conf.AlipayConfig;
import com.andata.pojo.ProductOrders;
import com.andata.service.ProOrdersService;
import com.andata.util.QRCodeUtil;
import net.sf.json.JSONObject;
import org.apache.ibatis.annotations.Param;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

@Controller
public class AliPayController {
    @Resource
    private ProOrdersService proOrdersService;
    /**
     * 支付逻辑
     * 1、商户系统调用支付宝预下单接口alipay.trade.precreate,获得该订单二维码图片地址。
     * 2、发起轮询获得支付结果:等待5秒后调用交易查询接口alipay.trade.query通过支付时传入的商户订单号(out_trade_no)查询支付结果(返回参数TRADE_STATUS),
     如果仍然返回等待用户付款(WAIT_BUYER_PAY),则再次等待5秒后继续查询,直到返回确切的支付结果(成功TRADE_SUCCESS 或 已撤销关闭TRADE_CLOSED),
     或是超出轮询时间。在最后一次查询仍然返回等待用户付款的情况下,必须立即调用交易撤销接口alipay.trade.cancel将这笔交易撤销,避免用户继续支付。
     * 3、除了主动轮询,也可以通过接受异步通知获得支付结果
     */
    /**
     * 阿里订单取消接口
     * 请求返回值示例:
     * {"alipay_trade_cancel_response":{"code":"40004","msg":"Business Failed","sub_code":"ACQ.INVALID_PARAMETER","sub_msg":"参数无效","out_trade_no":"20150320010101002",
     * "retry_flag":"N"},"sign":""}
     * @return
     * @throws AlipayApiException
     */
    @RequestMapping(value = "aliremove.do")
    @ResponseBody
    private Map<String, Object> remove(@Param("orderid")String orderid) throws AlipayApiException {
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //获得初始化的AlipayClient
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();//创建API对应的request类
        Map<String,Object> returnmap=new HashMap<>();
        try {
            //判断订单是否完成支付,完成支付的订单禁止撤销
            int i = this.proOrdersService.selectOrderStatus(orderid);
            if (i==1)
            {
                returnmap.put("type","0");
                returnmap.put("data","订单已支付,撤销订单失败");
            }else {
                Map<String,Object> map=new HashMap<>();
                map.put("out_trade_no",orderid);
                String returndata = JSONObject.fromObject(map).toString();
                request.setBizContent(returndata); //设置业务参数
                AlipayTradeCancelResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类
                JSONObject query_response = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_cancel_response");
                String code = query_response.getString("code");
                String msg = query_response.getString("msg");
                if (code.equals("10000") && msg.equals("Success")) {
                    System.out.println("阿里订单取消接口调用成功!");
                    returnmap.put("type","1");
                    returnmap.put("data","撤销订单成功");
                }else {
                    System.out.println("撤销订单请求失败");
                    returnmap.put("type","0");
                    returnmap.put("data",query_response.getString("sub_msg"));
                    System.out.println(query_response);//返回失败信息
                }
                //根据response中的结果继续业务逻辑处理
            }
        }catch (Exception e)
        {
            System.out.println("撤销订单异常");
            e.printStackTrace();
        }
        return returnmap;
    }

    /**
     * 阿里交易查询接口
     * out_trade_no	支付时传入的商户订单号,与trade_no必填一个
     *  trade_no	支付时返回的支付宝交易号,与out_trade_no必填一个
     *  请求返回值示例:
     *  {"alipay_trade_query_response":{"code":"10000","msg":"Success","buyer_logon_id":"159****4027","buyer_pay_amount":"0.01","buyer_user_id":"2088012351746164",
     *  "fund_bill_list":[{"amount":"0.01","fund_channel":"PCREDIT"}],"invoice_amount":"0.01","out_trade_no":"020910312752381","point_amount":"0.00","receipt_amount":"0.01",
     *  "send_pay_date":"2018-02-09 10:31:45","total_amount":"0.01","trade_no":"2018020921001004160275738069","trade_status":"TRADE_SUCCESS"},
     *  "sign":""}
     * @return
     * @throws Exception
     */
    @RequestMapping(value="/aliget")
    @ResponseBody
    private Map<String, Object> get(@Param("orderid")String orderid) throws AlipayApiException{
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //获得初始化的AlipayClient
        AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();//创建API对应的request类
        Map<String,Object> map=new HashMap<>();
        map.put("out_trade_no",orderid);
        String returndata = JSONObject.fromObject(map).toString();
        request.setBizContent(returndata); //设置业务参数
        AlipayTradeQueryResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类
        JSONObject jsonObject = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_query_response");
        String code = jsonObject.getString("code");
        String msg = jsonObject.getString("msg");
        Map<String,Object> returnmap=new HashMap<>();
        if (code.equals("10000") && msg.equals("Success"))
        {
            System.out.println("交易查询请求成功");
            String trade_status = jsonObject.getString("trade_status");
            if (trade_status.equals("TRADE_SUCCESS"))
            {
                returnmap.put("type","1");
                returnmap.put("data","支付成功");
            }else {
                returnmap.put("type","0");
                returnmap.put("data",trade_status);
            }
        }else {
            System.out.println("交易查询请求失败");
            returnmap.put("type","0");
            returnmap.put("data",jsonObject.getString("sub_msg"));
            System.out.println(jsonObject);//返回失败信息
        }
        return returnmap;
    }
    /**
     * @name 预下单请求,阿里获取二维码接口
     * @throws AlipayApiException
     * @Param out_trade_no 商户订单号,64个字符以内、只能包含字母、数字、下划线;需保证在商户端不重复
     * @Param total_amount 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 如果同时传入了【打折金额】,【不可打折金额】,
     * 【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】
     * @Param subject 订单标题
     * @Param store_id 商户门店编号
     * @Param timeout_express 该笔订单允许的最晚付款时间,逾期将关闭交易。
     * 取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。
     */
    @RequestMapping(value="/alipay.do")
    @ResponseBody
    private Map list(HttpServletResponse responses, @Param("orderid")String orderid) throws AlipayApiException{
        AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //获得初始化的AlipayClient
        AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//创建API对应的request类

        Map<String,Object> map=new HashMap<>();
        if (orderid.isEmpty())
        {
            map.put("type","2");
            map.put("data","订单号不能为空");
            return map;
        }
        //设置回调地址
        request.setNotifyUrl("http://www.andata.com.cn/aliPayCallBack.do");
        //根据订单号查询订单信息
        ProductOrders productOrders = this.proOrdersService.selectByOrderId(orderid);
        Map<String,Object> maps=new HashMap<>();
        maps.put("out_trade_no",productOrders.getOrdernumber());
        maps.put("total_amount","0.01");
        maps.put("subject","小编机器人纠错");
        maps.put("store_id","XB001");
        maps.put("timeout_express","1m");
        //把订单信息转换为json对象的字符串
        String postdata = JSONObject.fromObject(maps).toString();
        request.setBizContent(postdata);
        AlipayTradePrecreateResponse response = alipayClient.execute(request);
        String body = response.getBody();
        JSONObject jsonObject = JSONObject.fromObject(body);
        String qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code");
        //流输出
        ServletOutputStream sos = null;
        try {
            sos = responses.getOutputStream();
            //生成二维码
            QRCodeUtil.encode(qr_code, sos);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 支付宝支付成功回调
     */
    @RequestMapping(value = "aliPayCallBack.do")
    @ResponseBody
    public void aliPayCallBack(HttpServletResponse response, HttpServletRequest request) {
        System.out.println("支付宝回调成功");
        try {
            //获取支付宝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] + ",";
                }
                //乱码解决,这段代码在出现乱码时使用。
                //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
                params.put(name, valueStr);
            }
            boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.zfb_public_key, AlipayConfig.input_charset,"RSA2");
            // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)//
            String order_no = request.getParameter("out_trade_no"); // 获取订单号

//			String trade_no = request.getParameter("trade_no"); // 支付宝交易号
//			String total_amount = request.getParameter("total_amount"); // 获取总金额
//			String subject = new String(request.getParameter("subject")
//					.getBytes("ISO-8859-1"), "gbk");// 商品名称、订单名称
//			String body = "";
//			if (request.getParameter("body") != null) {
//				body = new String(request.getParameter("body").getBytes(
//						"ISO-8859-1"), "gbk");// 商品描述、订单备注、描述
//			}
//			String buyer_email = request.getParameter("buyer_email"); // 买家支付宝账号
            String trade_status = request.getParameter("trade_status"); // 交易状态
            // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)//
            if (flag==true) {// 验证成功
                try{
                    int i = this.proOrdersService.updateByOrderId(order_no);
                    if (i==1)
                    {
                        System.out.println("支付宝订单支付成功!");
                    }
                }catch (Exception e)
                {
                    System.out.println("支付宝支付异常");
                    e.printStackTrace();
                }
            }
            response.getWriter().write("success");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

现在,基本的代码都贴完了,生成二维码的逻辑和微信一样,拿到code_url后,用二维码生成工具类生成二维码,把他贴到网页上需要支付的页面,就成功了~

转载于:https://my.oschina.net/u/3021675/blog/1791751

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值