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

1package com.andata.controller; 2import com.alipay.api.AlipayApiException; 3import com.alipay.api.AlipayClient; 4import com.alipay.api.DefaultAlipayClient; 5import com.alipay.api.internal.util.AlipaySignature; 6import com.alipay.api.request.AlipayTradeCancelRequest; 7import com.alipay.api.request.AlipayTradePrecreateRequest; 8import com.alipay.api.request.AlipayTradeQueryRequest; 9import com.alipay.api.response.AlipayTradeCancelResponse; 10import com.alipay.api.response.AlipayTradePrecreateResponse; 11import com.alipay.api.response.AlipayTradeQueryResponse; 12import com.andata.conf.AlipayConfig; 13import com.andata.pojo.ProductOrders; 14import com.andata.service.ProOrdersService; 15import com.andata.util.QRCodeUtil; 16import net.sf.json.JSONObject; 17import org.apache.ibatis.annotations.Param; 18import org.springframework.stereotype.Controller; 19import org.springframework.web.bind.annotation.RequestMapping; 20import org.springframework.web.bind.annotation.ResponseBody; 21 22import javax.annotation.Resource; 23import javax.servlet.ServletOutputStream; 24import javax.servlet.http.HttpServletRequest; 25import javax.servlet.http.HttpServletResponse; 26import java.io.IOException; 27import java.util.HashMap; 28import java.util.Iterator; 29import java.util.Map; 30 31@Controller 32public class AliPayController { 33 @Resource 34 private ProOrdersService proOrdersService; 35 /** 36 * 支付逻辑 37 * 1、商户系统调用支付宝预下单接口alipay.trade.precreate,获得该订单二维码图片地址。 38 * 2、发起轮询获得支付结果:等待5秒后调用交易查询接口alipay.trade.query通过支付时传入的商户订单号(out_trade_no)查询支付结果(返回参数TRADE_STATUS), 39 如果仍然返回等待用户付款(WAIT_BUYER_PAY),则再次等待5秒后继续查询,直到返回确切的支付结果(成功TRADE_SUCCESS 或 已撤销关闭TRADE_CLOSED), 40 或是超出轮询时间。在最后一次查询仍然返回等待用户付款的情况下,必须立即调用交易撤销接口alipay.trade.cancel将这笔交易撤销,避免用户继续支付。 41 * 3、除了主动轮询,也可以通过接受异步通知获得支付结果 42 */ 43 /** 44 * 阿里订单取消接口 45 * 请求返回值示例: 46 * {"alipay_trade_cancel_response":{"code":"40004","msg":"Business Failed","sub_code":"ACQ.INVALID_PARAMETER","sub_msg":"参数无效","out_trade_no":"20150320010101002", 47 * "retry_flag":"N"},"sign":""} 48 * @return 49 * @throws AlipayApiException 50 */ 51 @RequestMapping(value = "aliremove.do") 52 @ResponseBody 53 private Map<String, Object> remove(@Param("orderid")String orderid) throws AlipayApiException { 54 AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //获得初始化的AlipayClient 55 AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();//创建API对应的request类 56 Map<String,Object> returnmap=new HashMap<>(); 57 try { 58 //判断订单是否完成支付,完成支付的订单禁止撤销 59 int i = this.proOrdersService.selectOrderStatus(orderid); 60 if (i==1) 61 { 62 returnmap.put("type","0"); 63 returnmap.put("data","订单已支付,撤销订单失败"); 64 }else { 65 Map<String,Object> map=new HashMap<>(); 66 map.put("out_trade_no",orderid); 67 String returndata = JSONObject.fromObject(map).toString(); 68 request.setBizContent(returndata); //设置业务参数 69 AlipayTradeCancelResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类 70 JSONObject query_response = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_cancel_response"); 71 String code = query_response.getString("code"); 72 String msg = query_response.getString("msg"); 73 if (code.equals("10000") && msg.equals("Success")) { 74 System.out.println("阿里订单取消接口调用成功!"); 75 returnmap.put("type","1"); 76 returnmap.put("data","撤销订单成功"); 77 }else { 78 System.out.println("撤销订单请求失败"); 79 returnmap.put("type","0"); 80 returnmap.put("data",query_response.getString("sub_msg")); 81 System.out.println(query_response);//返回失败信息 82 } 83 //根据response中的结果继续业务逻辑处理 84 } 85 }catch (Exception e) 86 { 87 System.out.println("撤销订单异常"); 88 e.printStackTrace(); 89 } 90 return returnmap; 91 } 92 93 /** 94 * 阿里交易查询接口 95 * out_trade_no 支付时传入的商户订单号,与trade_no必填一个 96 * trade_no 支付时返回的支付宝交易号,与out_trade_no必填一个 97 * 请求返回值示例: 98 * {"alipay_trade_query_response":{"code":"10000","msg":"Success","buyer_logon_id":"159****4027","buyer_pay_amount":"0.01","buyer_user_id":"2088012351746164", 99 * "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", 100 * "send_pay_date":"2018-02-09 10:31:45","total_amount":"0.01","trade_no":"2018020921001004160275738069","trade_status":"TRADE_SUCCESS"}, 101 * "sign":""} 102 * @return 103 * @throws Exception 104 */ 105 @RequestMapping(value="/aliget") 106 @ResponseBody 107 private Map<String, Object> get(@Param("orderid")String orderid) throws AlipayApiException{ 108 AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //获得初始化的AlipayClient 109 AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();//创建API对应的request类 110 Map<String,Object> map=new HashMap<>(); 111 map.put("out_trade_no",orderid); 112 String returndata = JSONObject.fromObject(map).toString(); 113 request.setBizContent(returndata); //设置业务参数 114 AlipayTradeQueryResponse response = alipayClient.execute(request);//通过alipayClient调用API,获得对应的response类 115 JSONObject jsonObject = JSONObject.fromObject(response.getBody()).getJSONObject("alipay_trade_query_response"); 116 String code = jsonObject.getString("code"); 117 String msg = jsonObject.getString("msg"); 118 Map<String,Object> returnmap=new HashMap<>(); 119 if (code.equals("10000") && msg.equals("Success")) 120 { 121 System.out.println("交易查询请求成功"); 122 String trade_status = jsonObject.getString("trade_status"); 123 if (trade_status.equals("TRADE_SUCCESS")) 124 { 125 returnmap.put("type","1"); 126 returnmap.put("data","支付成功"); 127 }else { 128 returnmap.put("type","0"); 129 returnmap.put("data",trade_status); 130 } 131 }else { 132 System.out.println("交易查询请求失败"); 133 returnmap.put("type","0"); 134 returnmap.put("data",jsonObject.getString("sub_msg")); 135 System.out.println(jsonObject);//返回失败信息 136 } 137 return returnmap; 138 } 139 /** 140 * @name 预下单请求,阿里获取二维码接口 141 * @throws AlipayApiException 142 * @Param out_trade_no 商户订单号,64个字符以内、只能包含字母、数字、下划线;需保证在商户端不重复 143 * @Param total_amount 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] 如果同时传入了【打折金额】,【不可打折金额】, 144 * 【订单总金额】三者,则必须满足如下条件:【订单总金额】=【打折金额】+【不可打折金额】 145 * @Param subject 订单标题 146 * @Param store_id 商户门店编号 147 * @Param timeout_express 该笔订单允许的最晚付款时间,逾期将关闭交易。 148 * 取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。 149 */ 150 @RequestMapping(value="/alipay.do") 151 @ResponseBody 152 private Map list(HttpServletResponse responses, @Param("orderid")String orderid) throws AlipayApiException{ 153 AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.ServiceUrl, AlipayConfig.app_id, AlipayConfig.private_key, "json", AlipayConfig.input_charset, AlipayConfig.zfb_public_key, "RSA2"); //获得初始化的AlipayClient 154 AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();//创建API对应的request类 155 156 Map<String,Object> map=new HashMap<>(); 157 if (orderid.isEmpty()) 158 { 159 map.put("type","2"); 160 map.put("data","订单号不能为空"); 161 return map; 162 } 163 //设置回调地址 164 request.setNotifyUrl("http://www.andata.com.cn/aliPayCallBack.do"); 165 //根据订单号查询订单信息 166 ProductOrders productOrders = this.proOrdersService.selectByOrderId(orderid); 167 Map<String,Object> maps=new HashMap<>(); 168 maps.put("out_trade_no",productOrders.getOrdernumber()); 169 maps.put("total_amount","0.01"); 170 maps.put("subject","小编机器人纠错"); 171 maps.put("store_id","XB001"); 172 maps.put("timeout_express","1m"); 173 //把订单信息转换为json对象的字符串 174 String postdata = JSONObject.fromObject(maps).toString(); 175 request.setBizContent(postdata); 176 AlipayTradePrecreateResponse response = alipayClient.execute(request); 177 String body = response.getBody(); 178 JSONObject jsonObject = JSONObject.fromObject(body); 179 String qr_code = jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code"); 180 //流输出 181 ServletOutputStream sos = null; 182 try { 183 sos = responses.getOutputStream(); 184 //生成二维码 185 QRCodeUtil.encode(qr_code, sos); 186 } catch (IOException e) { 187 e.printStackTrace(); 188 } catch (Exception e) { 189 e.printStackTrace(); 190 } 191 return map; 192 } 193 194 /** 195 * 支付宝支付成功回调 196 */ 197 @RequestMapping(value = "aliPayCallBack.do") 198 @ResponseBody 199 public void aliPayCallBack(HttpServletResponse response, HttpServletRequest request) { 200 System.out.println("支付宝回调成功"); 201 try { 202 //获取支付宝POST过来反馈信息 203 Map<String,String> params = new HashMap<String,String>(); 204 Map requestParams = request.getParameterMap(); 205 for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) { 206 String name = (String) iter.next(); 207 String[] values = (String[]) requestParams.get(name); 208 String valueStr = ""; 209 for (int i = 0; i < values.length; i++) { 210 valueStr = (i == values.length - 1) ? valueStr + values[i] 211 : valueStr + values[i] + ","; 212 } 213 //乱码解决,这段代码在出现乱码时使用。 214 //valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8"); 215 params.put(name, valueStr); 216 } 217 boolean flag = AlipaySignature.rsaCheckV1(params, AlipayConfig.zfb_public_key, AlipayConfig.input_charset,"RSA2"); 218 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以下仅供参考)// 219 String order_no = request.getParameter("out_trade_no"); // 获取订单号 220 221// String trade_no = request.getParameter("trade_no"); // 支付宝交易号 222// String total_amount = request.getParameter("total_amount"); // 获取总金额 223// String subject = new String(request.getParameter("subject") 224// .getBytes("ISO-8859-1"), "gbk");// 商品名称、订单名称 225// String body = ""; 226// if (request.getParameter("body") != null) { 227// body = new String(request.getParameter("body").getBytes( 228// "ISO-8859-1"), "gbk");// 商品描述、订单备注、描述 229// } 230// String buyer_email = request.getParameter("buyer_email"); // 买家支付宝账号 231 String trade_status = request.getParameter("trade_status"); // 交易状态 232 // 获取支付宝的通知返回参数,可参考技术文档中页面跳转同步通知参数列表(以上仅供参考)// 233 if (flag==true) {// 验证成功 234 try{ 235 int i = this.proOrdersService.updateByOrderId(order_no); 236 if (i==1) 237 { 238 System.out.println("支付宝订单支付成功!"); 239 } 240 }catch (Exception e) 241 { 242 System.out.println("支付宝支付异常"); 243 e.printStackTrace(); 244 } 245 } 246 response.getWriter().write("success"); 247 } catch (Exception e) { 248 e.printStackTrace(); 249 } 250 } 251}

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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )