背景:突然有一个整合支付宝、微信、银联三种支付方式在一个接口下,通过简单的配置即可实现支付的想法。故,想不如做,马上动手搞一下并做记录。首先了解一下支付宝。
一、准备工作(沙箱模式):
1、注册蚂蚁开放平台——点击研发服务
2、生成公钥、秘钥,查看APPID
3、安卓手机下载沙箱版支付宝
4、在此查看,沙箱支付宝用到的账号和密码
二、代码阶段(此处是我任意找到的一个项目,将代码集成进去的。关于代码逻辑,注释已经写得很清楚了自己看,不做赘述),直接上代码:
1、代码结构:
2、pom文件配置
<!--支付宝--> <dependency> <groupId>com.alipay.sdk</groupId> <artifactId>alipay-sdk-java</artifactId> <version>3.1.0</version> </dependency> <!--支付宝--><!-- https://mvnrepository.com/artifact/com.google.code.gson/gson --> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.2</version> </dependency> <!-- 使用注释处理器生成自己的元数据--> <dependency> <groupId>org.springframework.boot </groupId> <artifactId>spring-boot-configuration-processor</artifactId> <optional>true</optional> </dependency>
3、新建并配置alipay.properties
#需要配置,支付宝私钥(生产环境和沙箱环境生成方式稍微有点差别) ALIPAY.PRIVATEKEY=你生成的应用私钥 #需要配置,支付宝公钥(生产环境和沙箱环境生成方式稍微有点差别) ALIPAY.PUBLICKEY=你生成的应用公钥 #支付宝解签公钥(这个需要注意一下) ALIPAY.RETURNPUBLICKEY=支付宝公钥(如果找不到,请看本教程“准备工作——第2步”) #支付宝应用APPID ALIPAY.APPID=你的应用APPID #支付宝正式网关 #ALIPAY.SERVER=https://openapi.alipay.com/gateway.do #支付宝沙箱网关 ALIPAY.SERVER=https://openapi.alipaydev.com/gateway.do #公网可以访问的地址 ALIPAY.NOTIFY_URL=http://localhost:8080/pay/notify #公网可以访问的地址 ALIPAY.RETURNA_URL=http://localhost:8080/pay/notify ALIPAY.SIGN=RSA2
4、AlipayConfig.java的代码
package com.jiao.tangtang.common.config; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; @Configuration @PropertySource(value = {"classpath:alipay.properties"}) @ConfigurationProperties public class AlipayConfig { @Value("${ALIPAY.APPID}") private String alipay_app_id; @Value("${ALIPAY.PRIVATEKEY}") private String merchant_private_key; @Value("${ALIPAY.PUBLICKEY}") private String alipay_public_key; @Value("${ALIPAY.RETURNPUBLICKEY}") private String alipay_return_public_key; @Value("${ALIPAY.NOTIFY_URL}") private String alipay_notify_url; @Value("${ALIPAY.RETURNA_URL}") private String return_url; @Value("${ALIPAY.SIGN}") private String sign_type; // private String charset = "utf-8"; @Value("${ALIPAY.SERVER}") private String gatewayUrL; public String getAlipay_app_id() { return alipay_app_id; } public void setAlipay_app_id(String alipay_app_id) { this.alipay_app_id = alipay_app_id; } public String getMerchant_private_key() { return merchant_private_key; } public void setMerchant_private_key(String merchant_private_key) { this.merchant_private_key = merchant_private_key; } public String getAlipay_public_key() { return alipay_public_key; } public void setAlipay_public_key(String alipay_public_key) { this.alipay_public_key = alipay_public_key; } public String getAlipay_return_public_key() { return alipay_return_public_key; } public void setAlipay_return_public_key(String alipay_return_public_key) { this.alipay_return_public_key = alipay_return_public_key; } public String getAlipay_notify_url() { return alipay_notify_url; } public void setAlipay_notify_url(String alipay_notify_url) { this.alipay_notify_url = alipay_notify_url; } public String getReturn_url() { return return_url; } public void setReturn_url(String return_url) { this.return_url = return_url; } public String getSign_type() { return sign_type; } public void setSign_type(String sign_type) { this.sign_type = sign_type; } public String getGatewayUrL() { return gatewayUrL; } public void setGatewayUrL(String gatewayUrL) { this.gatewayUrL = gatewayUrL; } }
5、AlipayVo.java
package com.jiao.tangtang.entity; import java.io.Serializable; public class AlipayVo implements Serializable { // 订单名称 private String subject; //商户网站唯一订单号 private String out_trade_no; //该笔订单允许的最晚付款时间 private String timeout_express; //付款金额 private String total_amount; //销售产品码,与支付宝签约的产品码名称 private String product_code; //订单描述 private String body; public String getSubject() { return subject; } public void setSubject(String subject) { this.subject = subject; } public String getOut_trade_no() { return out_trade_no; } public void setOut_trade_no(String out_trade_no) { this.out_trade_no = out_trade_no; } public String getTimeout_express() { return timeout_express; } public void setTimeout_express(String timeout_express) { this.timeout_express = timeout_express; } public String getTotal_amount() { return total_amount; } public void setTotal_amount(String total_amount) { this.total_amount = total_amount; } public String getProduct_code() { return product_code; } public void setProduct_code(String product_code) { this.product_code = product_code; } public String getBody() { return body; } public void setBody(String body) { this.body = body; } }
6、AlipayController.java
package com.jiao.tangtang.controller; import com.alipay.api.AlipayApiException; import com.alipay.api.AlipayClient; import com.alipay.api.DefaultAlipayClient; import com.alipay.api.domain.AlipayTradeAppPayModel; import com.alipay.api.internal.util.AlipaySignature; import com.alipay.api.request.AlipayTradeAppPayRequest; import com.alipay.api.request.AlipayTradePagePayRequest; import com.alipay.api.response.AlipayTradeAppPayResponse; import com.google.gson.Gson; import com.jiao.tangtang.entity.AlipayVo; import com.jiao.tangtang.common.config.AlipayConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import java.util.HashMap; import java.util.Iterator; import java.util.Map; @Controller() @RequestMapping("pay") public class AlipayController { @Autowired private AlipayConfig aliPayConfig; @RequestMapping("/alipayWeb") @ResponseBody private String alipaytest(String orderid, String totalAmount, String subject, String body) throws AlipayApiException { AlipayVo vo = new AlipayVo(); //订单号 vo.setOut_trade_no(orderid); //支付金额 vo.setTotal_amount(totalAmount); //商品名称 vo.setSubject(subject); //商品描述 vo.setBody(body); vo.setProduct_code("FAST_INSTANT_TRADE_PAY"); //这个是固定的 String json = new Gson().toJson(vo); AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.getGatewayUrL() , aliPayConfig.getAlipay_app_id(), aliPayConfig.getMerchant_private_key() , "json", "UTF-8", aliPayConfig.getAlipay_public_key() , aliPayConfig.getSign_type()); // 设置请求参数 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(aliPayConfig.getReturn_url()); //设置支付宝可访问外网URL alipayRequest.setNotifyUrl(aliPayConfig.getAlipay_notify_url()); alipayRequest.setBizContent(json); String result = alipayClient.pageExecute(alipayRequest).getBody(); return result; //这里生成一个表单,会自动提交 } @RequestMapping("/notify") @ResponseBody private String alipayNotify(HttpServletRequest request, String out_trade_no, String trade_no, String trade_status) throws AlipayApiException { Map<String, String> map = new HashMap<>(); Map<String, String[]> requestParams = request.getParameterMap(); for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) { String name = iter.next(); String[] values = requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } map.put(name, valueStr); } // 买家付款账号 // String buyer_logon_id = map.get("buyer_logon_id"); // 交易状态 // trade_status = map.get("trade_status"); // 商户订单号 // out_trade_no = map.get("out_trade_no"); // 支付宝交易号 // trade_no = map.get("trade_no"); //商户编号 // String stord_id = map.get("body"); //充值硬币 // Integer coin_num = Integer.parseInt(map.get("passback_params")); boolean signVerified = false; try { signVerified = AlipaySignature.rsaCheckV1(map,aliPayConfig.getAlipay_return_public_key(), "UTF-8",aliPayConfig.getSign_type()); } catch (AlipayApiException e) { e.printStackTrace(); return ("fail");// 验签发生异常,则直接返回失败 } if (signVerified) { // TODO //处理你的业务逻辑,更细订单状态等 System.out.println("****************处理业务逻辑,更细订单状态****************"); return ("success"); } else { return ("fail"); } } @RequestMapping("/return") @ResponseBody private Map<String, Object> paymentresult(HttpServletRequest request, String out_trade_no, String trade_no, String trade_status) throws AlipayApiException { Map<String, Object> resultMap = new HashMap<>(); Map<String, String> map = new HashMap<>(); Map<String, String[]> requestParams = request.getParameterMap(); for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) { String name = iter.next(); String[] values = requestParams.get(name); String valueStr = ""; for (int i = 0; i < values.length; i++) { valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ","; } map.put(name, valueStr); } // 买家付款账号 // String buyer_logon_id = map.get("buyer_logon_id"); // 交易状态 // trade_status = map.get("trade_status"); // 商户订单号 // out_trade_no = map.get("out_trade_no"); // 支付宝交易号 // trade_no = map.get("trade_no"); //商户编号 // String stord_id = map.get("body"); //充值硬币 // Integer coin_num = Integer.parseInt(map.get("passback_params")); boolean signVerified = false; try { signVerified = AlipaySignature.rsaCheckV1(map, aliPayConfig.getAlipay_return_public_key(), "UTF-8", aliPayConfig.getSign_type()); } catch (AlipayApiException e) { e.printStackTrace(); resultMap.put("1", "验签发生异常"); return resultMap;// 验签发生异常,则直接返回失败 } if (signVerified) { // TODO //处理你的业务逻辑,更细订单状态等 resultMap.put("0", "处理成功!"); return resultMap; } else { resultMap.put("1", "验证失败,不去更新状态!"); return resultMap; } } @RequestMapping("/alipayAndroid") @ResponseBody public Map<String,Object> getAliPayOrderStr(AlipayVo tOrder) { Map<String, Object> resultMap = new HashMap<>(); //最终返回加签之后的,app需要传给支付宝app的订单信息字符串 System.out.println("==================支付宝下单,商户订单号为:" + tOrder.getOut_trade_no()); try { //实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息 AlipayClient alipayClient = new DefaultAlipayClient(aliPayConfig.getGatewayUrL() , aliPayConfig.getAlipay_app_id(), aliPayConfig.getMerchant_private_key() , "json", "UTF-8", aliPayConfig.getAlipay_public_key() , aliPayConfig.getSign_type()); //实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay AlipayTradeAppPayRequest ali_request = new AlipayTradeAppPayRequest(); //SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式 AlipayTradeAppPayModel model = new AlipayTradeAppPayModel(); //业务参数传入,可以传很多,参考API //model.setPassbackParams(URLEncoder.encode(request.getBody().toString())); //公用参数(附加数据) model.setBody(tOrder.getBody()); //对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。 model.setSubject(tOrder.getSubject()); //商品名称 model.setOutTradeNo(tOrder.getOut_trade_no()); //商户订单号(自动生成) // model.setTimeoutExpress("30m"); //交易超时时间 model.setTotalAmount(tOrder.getTotal_amount()); //支付金额 model.setProductCode("QUICK_MSECURITY_PAY"); //销售产品码(固定值) ali_request.setBizModel(model); ali_request.setNotifyUrl(aliPayConfig.getAlipay_notify_url()); //异步回调地址(后台) ali_request.setReturnUrl(aliPayConfig.getReturn_url()); //同步回调地址(APP) // 这里和普通的接口调用不同,使用的是sdkExecute AlipayTradeAppPayResponse alipayTradeAppPayResponse = alipayClient.sdkExecute(ali_request); //返回支付宝订单信息(预处理) String orderString = alipayTradeAppPayResponse.getBody();//就是orderString 可以直接给APP请求,无需再做处理。 resultMap.put("0", "加签成功!"); resultMap.put("data", orderString); } catch (AlipayApiException e) { e.printStackTrace(); resultMap.put("1", "与支付宝交互出错,未能生成订单,请检查代码!"); resultMap.put("data", null); } return resultMap; } }
三、至此代码就结束了,那么测试该怎么办呢:
1、直接调用AlipayController中的方法,最简单的方式就是,
例如:localhost:8080/pay/alipayWeb?orderid=参数1&totalAmount=参数2&subject=参数3&body=参数4(参数为alipaytest方法中需要传的参),
执行这个方法后,会生成支付二维码。
2、使用沙箱支付宝,扫码支付
四、那么正式环境该怎么办呢:
1、首先需要在开放平台中进行创建,然后等着审核通过
2、审核通过后,在你的应用上配置好对应的公钥,查看自己的APPID,最后修改掉alipay.properties配置文件中对应的内容,就可以了,当然正式的还是不太一样的,这个在调试的过程中就会发现。
至此就全部结束了。