支付宝沙箱之电脑网站支付 £神魔★判官ぃ 2022-04-13 04:37 293阅读 0赞 > ## [《支付宝沙箱链接》][Link 1] ## > > ## [《电脑网站支付快速接入文档》][Link 2] ## > 引入SKD: > > ## [Maven依赖][Maven] ## 代码: public class AlipayVO implements Serializable { private static final long serialVersionUID = 1L; /** * 订单名称 */ private String subject; /** * 商户网站唯一订单号 */ private String out_trade_no; /** * 该笔订单允许的最晚付款时间 */ private String timeout_express; /** * 付款金额 */ private String total_amount; /** * 销售产品码,与支付宝签约的产品码名称 */ private String product_code; // 省略getter和setter } /* * *类名:AlipayConfig *功能:基础配置类 *详细:设置帐户有关信息及返回路径 *修改日期:2017-04-05 *说明: *以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。 *该代码仅供学习和研究支付宝接口使用,只是提供一个参考。 */ public class AlipayConfig { //↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓ // 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号 public static String app_id = ""; // 商户私钥,您的PKCS8格式RSA2私钥 public static String merchant_private_key = ""; // 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。 public static String alipay_public_key = ""; // 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 public static String notify_url = "http://vz6snm.natappfree.cc/ocPortal/alipay/notify"; // 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问 public static String return_url = "http://localhost/ocPortal/alipay/return"; // 签名方式 public static String sign_type = "RSA2"; // 字符编码格式 public static String charset = "UTF-8"; // 支付宝网关 // 正式环境 // public static String gateway_url = "https://openapi.alipay.com/gateway.do"; // 沙箱环境 public static String gateway_url = "https://openapi.alipaydev.com/gateway.do"; //↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑ } @RequestMapping("/alipay") @Controller public class AlipayController { /** * 支付网站扫码支付接口-统一下单支付接口 * @return * @throws AlipayApiException */ @RequestMapping(value = "/pay", method = RequestMethod.GET) @ResponseBody private String alipayPay(@RequestParam("subscribeId") Long subscribeId) throws AlipayApiException { UserSubscribe userSubscribe = subscribeService.getById(subscribeId); AlipayVO vo = new AlipayVO(); vo.setOut_trade_no(UUID.randomUUID().toString().replace("-", "")); vo.setTotal_amount("0.01"); vo.setSubject("商品名称"); vo.setProduct_code("FAST_INSTANT_TRADE_PAY"); //这个是固定的 String json = new Gson().toJson(vo); AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gateway_url, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); // 设置请求参数 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(AlipayConfig.return_url); alipayRequest.setNotifyUrl(AlipayConfig.notify_url); alipayRequest.setBizContent(json); String result = alipayClient.pageExecute(alipayRequest).getBody(); return result; //这里生成一个表单,会自动提交 } /** * 支付宝服务器异步通知页面 * @param request * @param out_trade_no 商户订单号 * @param trade_no 支付宝交易凭证号 * @param trade_status 交易状态 * @return * @throws AlipayApiException */ @RequestMapping("/notify") @ResponseBody public String alipayNotify(HttpServletRequest request, String out_trade_no, String trade_no, String trade_status) throws AlipayApiException { Map<String, String> params = getParamsMap(request); System.out.println("notify out_trade_no:" + out_trade_no); System.out.println("notify trade_no:" + trade_no); System.out.println("notify trade_status:" + trade_status); System.out.println("notify subject" + params.get("subject")); // 验证签名 boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); System.out.println("notify signVerified:" + signVerified); if (signVerified) { // 处理业务逻辑,更细订单状态等 // 支付成功 if("TRADE_SUCCESS".equals(trade_status)){ // return success可阻止支付宝继续回调 return "success"; } return "fail"; } else { return "fail"; } } /** * 支付宝服务器同步通知页面 * @param request * @param out_trade_no 商户订单号 * @param trade_no 支付宝交易凭证号 * @param total_amount 交易状态 * @return * @throws AlipayApiException */ @RequestMapping("/return") public String alipayReturn(HttpServletRequest request, String out_trade_no, String trade_no, String total_amount) throws AlipayApiException { Map<String, String> params = getParamsMap(request); System.out.println("return out_trade_no:" + out_trade_no); System.out.println("return trade_no:" + trade_no); System.out.println("return total_amount:" + total_amount); // 验证签名 boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.alipay_public_key, AlipayConfig.charset, AlipayConfig.sign_type); System.out.println("return signVerified:"+signVerified); if(signVerified) { } else { } return "redirect:/user/subscribe.html"; } private Map<String, String> getParamsMap(HttpServletRequest request) { Map<String,String> params = new HashMap<>(); 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] + ","; } //乱码解决,这段代码在参数出现乱码时使用 // try { // valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); params.put(name, valueStr); // } catch (UnsupportedEncodingException e) { // e.printStackTrace(); // } } return params; } } 注意: 1、异步回调的路径必须暴露在外网下,而同步回调路径可根据环境选择 2、异步回调路径是被支付宝调用的,所以需要注意是否会被自己系统的登录拦截功能所拦截 3、修改订单的状态最好在异步回调里处理,同步回调只负责用户浏览器的跳转 4、AlipayConfig的参数需要确保正确 # 问题: # ## 1、支付宝回调验签失败解决办法 ## 支付宝有两个重载的方法。如果使用的是RSA加密的话,就调用下面这个方法。 boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, "UTF-8"); 如果使用的是RSA2加密的话,就调用下面这个方法。 boolean signVerified = AlipaySignature.rsaCheckV1(params, AlipayConfig.ALIPAY_PUBLIC_KEY, "UTF-8", "RSA2"); ## 2、支付宝同步和异步验签结果不一致的解决方法 ## 同步验签正确、而异步验签错误,可能是参数中有中文乱码导致的,一般就是subject这个参数,可以在回调函数中打印出该参数,查看是否乱码。 valueStr = new String(valueStr.getBytes("ISO-8859-1"), "UTF-8"); [Link 1]: https://openhome.alipay.com/platform/appDaily.htm?tab=info [Link 2]: https://docs.open.alipay.com/270/105899/ [Maven]: https://mvnrepository.com/artifact/com.alipay.sdk/alipay-sdk-java
还没有评论,来说两句吧...