java做支付宝 app支付(证书模式)

记录支付java证书模式的接入方法

准备工作

  1. 注册支付宝商户,实名认证,获取appid
  2. 申请支付宝公钥证书

引入jar:

     <dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.9.124.ALL</version></dependency>

直接上代码:

Controller:

package com.wf.ew.api.controller;import com.wf.ew.alipay.service.WhAliPayService;
import com.wf.ew.annotation.Login;
import com.wf.ew.common.JsonResult;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/api")
@Api(value = "支付宝支付", tags = {"\\"})
public class AlipayController {@Resourceprivate WhAliPayService whAliPayService;//支付宝支付统一下单接口(公钥证书方式)@Login@PostMapping("toAlipay")@ApiOperation(value = "去支付宝支付")@ApiImplicitParams({@ApiImplicitParam(name = "orderNo", value = "订单编号", required = true, paramType = "query", dataType = "String"),})public JsonResult builderPay(String orderNo) {Map<String, Object> map = new HashMap<>();try {String orderSgin = this.whAliPayService.aliPayCertUnifiedOrder(orderNo);map.put("orderSgin", orderSgin);return JsonResult.ok().put("data", map);} catch (Exception e) {return JsonResult.error("支付异常");}}/*** 支付宝回调** @param request 请求对象* @return success||fail* @throws Exception 解签异常*/@RequestMapping("/alipayNotify")public String notify(HttpServletRequest request) throws Exception {return this.whAliPayService.aliPayCertNotify(request);}
}

Service:

package com.wf.ew.alipay.service.impl;import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.request.AlipayTradeAppPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.wf.ew.alipay.service.WhAliPayService;
import com.wf.ew.alipay.utils.AlipayUtil;
import com.wf.ew.system.model.WhAlipayKey;
import com.wf.ew.system.model.WhUserSafe;
import com.wf.ew.system.service.WhAlipayKeyBo;
import com.wf.ew.system.service.WhUserSafeBo;
import com.wf.ew.system.xys.model.WhOrderItemModel;
import com.wf.ew.system.xys.model.WhOrderModel;
import com.wf.ew.system.xys.model.WhOrderSettlementModel;
import com.wf.ew.system.xys.service.WhOrderItemService;
import com.wf.ew.system.xys.service.WhOrderService;
import com.wf.ew.system.xys.service.WhOrderSettlementService;
import com.wf.ew.wechatpay.util.PayConfigUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.List;@Service("whAliPayService")
public class WhAliPayServiceImpl implements WhAliPayService {private static final Logger log = LoggerFactory.getLogger(WhAliPayServiceImpl.class);private static PayConfigUtils config = new PayConfigUtils();@Resourceprivate WhAlipayKeyBo whAlipayKeyBo;@Resourceprivate WhOrderService whOrderService;@Resourceprivate WhOrderItemService whOrderItemService;@Resourceprivate WhOrderSettlementService whOrderSettlementService;@Resourceprivate WhUserSafeBo whUserSafeBo;@Overridepublic String aliPayCertUnifiedOrder(String orderNo) throws Exception {//构造支付宝请求对象WhAlipayKey alipayKey = this.whAlipayKeyBo.selectById(1);String privateKey = alipayKey.getPrivateKey();//从数据库获取应用私钥AlipayClient alipayClient = AlipayUtil.buildAliClient(privateKey);//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.payAlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();WhOrderModel whOrderModel = whOrderService.selectOne(new EntityWrapper<WhOrderModel>().eq("order_number", orderNo));if (whOrderModel == null) {throw new Exception("订单不存在");}if (whOrderModel.getStatus() != 1) {throw new Exception("此订单已支付或订单异常!");}List<WhOrderItemModel> itemList = this.whOrderItemService.selectList(new EntityWrapper<WhOrderItemModel>().eq("order_number", orderNo));StringBuilder builder = new StringBuilder();for (WhOrderItemModel item : itemList) {builder.append(item.getGoodsName());builder.append(",");}builder.deleteCharAt(builder.length() - 1);log.info("商品名称字符串==" + builder);model.setBody(builder.toString());//对一笔交易的具体描述信息。如果是多种商品,请将商品描述字符串累加传给body。例:Iphone6 16Gmodel.setSubject(builder.toString()); //商品的标题/交易标题/订单标题/订单关键字等。model.setOutTradeNo(orderNo);//商户网站唯一订单号model.setTimeoutExpress("90m");//该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。 该参数数值不接受小数点, 如 1.5h,可转换为 90m。// model.setTotalAmount(whOrderModel.getActualAmount().toString());model.setTotalAmount("0.01");//订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000]try {String param = builder.toString();String encodeParam = URLEncoder.encode(param, "utf-8");model.setPassbackParams(encodeParam);//设置公共参数,非必填request.setBizModel(model);request.setNotifyUrl(config.al_alipay_notify_url);//这里和普通的接口调用不同,使用的是sdkExecuteAlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);return response.getBody();} catch (AlipayApiException | UnsupportedEncodingException e) {e.printStackTrace();return "报错了";}}@Overridepublic String aliPayCertNotify(HttpServletRequest request) throws Exception {// 一定要验签,防止黑客篡改参数Map<String, String[]> parameterMap = request.getParameterMap();StringBuilder notifyBuild = new StringBuilder("/****************************** alipay notify ******************************/\n");parameterMap.forEach((key, value) -> notifyBuild.append(key + "=" + value[0] + "\n"));log.info(notifyBuild.toString());log.info("通知回调:支付宝回调日志信息信息:" + request.getParameterMap().toString());boolean flag = AlipayUtil.rsaCheckV1(request);if (flag) {String lCharset = "ISO-8859-1";String rCharset = "UTF-8";String mySellerId = "1234567890";//支付商户id/*** 商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号, 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额), 同时需要校验通知中的seller_id(或者seller_email)* 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),** 上述有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。* 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。*/// 交易状态String tradeStatus = new String(request.getParameter("trade_status").getBytes(lCharset), rCharset);// 商户订单号String outTradeNo = new String(request.getParameter("out_trade_no").getBytes(lCharset), rCharset);// 支付宝交易号String tradeNo = new String(request.getParameter("trade_no").getBytes(lCharset), rCharset);// 付款金额String totalAmount = new String(request.getParameter("total_amount").getBytes(lCharset), rCharset);String buyerLogonId = new String(request.getParameter("buyer_logon_id").getBytes(lCharset), rCharset);//手机号后四位String invoiceAmount = new String(request.getParameter("invoice_amount").getBytes(lCharset), rCharset);String receiptAmount = new String(request.getParameter("receipt_amount").getBytes(lCharset), rCharset);String buyerPayAmount = new String(request.getParameter("buyer_pay_amount").getBytes(lCharset), rCharset);String sellerId = new String(request.getParameter("seller_id").getBytes(lCharset), rCharset);String pointAmount = new String(request.getParameter("point_amount").getBytes(lCharset), rCharset);String passbackParams = new String(request.getParameter("passback_params").getBytes(lCharset), rCharset);// TRADE_FINISHED(表示交易已经成功结束,并不能再对该交易做后续操作);// TRADE_SUCCESS(表示交易已经成功结束,可以对该交易做后续操作,如:分润、退款等);// 这里就是调用自己的逻辑代码 修改订单状态及用户余额之类的return "success";}return "fail";}}

AlipayUtil


package com.wf.ew.alipay.utils;import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.internal.util.AlipaySignature;
import com.wf.ew.wechatpay.util.PayConfigUtils;import javax.servlet.http.HttpServletRequest;
import java.security.Security;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;public class AlipayUtil {private static PayConfigUtils config = new PayConfigUtils();/*** 构建支付宝基本参数** @param privateKey 应用私钥* @return 对象* @throws AlipayApiException 支付异常*/public static AlipayClient buildAliClient(String privateKey) throws AlipayApiException {//构造clientCertAlipayRequest certAlipayRequest = new CertAlipayRequest();//设置网关地址certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");//设置应用IdcertAlipayRequest.setAppId(config.al_appid);//设置应用私钥certAlipayRequest.setPrivateKey(privateKey);//设置请求格式,固定值jsoncertAlipayRequest.setFormat("json");//设置字符集certAlipayRequest.setCharset("UTF-8");//设置签名类型certAlipayRequest.setSignType(config.al_sign_type);//设置应用公钥证书路径certAlipayRequest.setCertPath(config.al_app_cert_path);//设置支付宝公钥证书路径certAlipayRequest.setAlipayPublicCertPath(config.al_alipay_cert_path);//设置支付宝根证书路径certAlipayRequest.setRootCertPath(config.al_alipay_root_cert_path);//构造clientAlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);return alipayClient;}/*** 校验签名 证书模式** @param request 请求对象* @return 是 /否* @throws AlipayApiException 支付异常*/public static boolean rsaCheckV1(HttpServletRequest request) throws AlipayApiException {//获取支付宝POST过来反馈信息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] + ",";}//乱码解决,这段代码在出现乱码时使用。//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");params.put(name, valueStr);}//切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。//boolean AlipaySignature.rsaCertCheckV1(Map<String, String> params, String publicKeyCertPath, String charset,String signType)Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());//解决 no such provider: BC异常boolean flag = AlipaySignature.rsaCertCheckV1(params, config.al_alipay_cert_path, "UTF-8", config.al_sign_type);return flag;}}
package com.wf.ew.wechatpay.util;import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;import java.io.InputStream;
import java.util.Properties;/*** 读取微信支付配置文件*/
public class PayConfigUtils {private static final Log log = LogFactory.getLog(PayConfigUtils.class);public static String appid;//微信appiidpublic static String mch_id;//微信商户idpublic static String notify_url;//微信支付回调地址public static String check_name;//微信提现是否强制实名public static String api_key;//微信支付接口秘钥public static String cert_path;//微信提现证书路径public static String al_appid;//支付宝appidpublic static String al_app_cert_path;//支付宝公钥证书public static String al_alipay_cert_path;//支付宝公钥证书路径public static String al_alipay_root_cert_path;//支付宝根证书路径public static String al_alipay_notify_url;//支付宝支付回调地址public static String al_sign_type;//支付宝签名类型static {try {InputStream is = PayConfigUtils.class.getResourceAsStream("/payConfig.properties");Properties properties = new Properties();properties.load(is);appid = properties.getProperty("wx.appid");mch_id = properties.getProperty("wx.mch_id");notify_url = properties.getProperty("wx.notify_url");check_name = properties.getProperty("wx.check_name");api_key = properties.getProperty("wx.api_key");cert_path = properties.getProperty("wx.cert_path");al_appid = properties.getProperty("al.appid");al_app_cert_path = properties.getProperty("al.app_cert_path");al_alipay_cert_path = properties.getProperty("al.alipay_cert_path");al_alipay_root_cert_path = properties.getProperty("al.alipay_root_cert_path");al_alipay_notify_url = properties.getProperty("al.alipay_notify_url");al_sign_type = properties.getProperty("al.sign_type");} catch (Exception ex) {log.debug("加载配置文件:" + ex.getMessage());}}
}

payConfig.properties:

#appid
wx.appid=
#商户id
wx.mch_id=
#支付回调地址
wx.notify_url=
#是否检测实名
wx.check_name=NO_CHECK
#微信支付API秘钥
wx.api_key=
#微信企业付款证书地址
wx.cert_path=/usr/local/project/apiclient_cert.p12#支付宝appid
al.appid=
#支付宝公钥证书
al.app_cert_path=/usr/local/cert/appCertPublicKey_2021001159693557.crt
#支付宝公钥证书路径
al.alipay_cert_path=/usr/local/cert/alipayCertPublicKey_RSA2.crt
#支付宝根证书路径
al.alipay_root_cert_path=/usr/local/cert/alipayRootCert.crt
#回调地址
al.alipay_notify_url=
#签名类型
al.sign_type=RSA2

1、 我用的是springboot2.x,所有properties文件放在resources目录下,支付宝证书存放在linux服务器上,所路径位置根据自己项目进行配置即可。

java做支付宝支付(证书模式)相关推荐

  1. SpringBoot 接入支付宝支付-证书模式

    SpringBoot 接入支付宝支付-证书模式 满足一下条件 1.注册支付宝商户,实名认证,获取APPID 2.申请支付宝公钥证书 3.有些复杂具体还是按照官方引导进行操作 产品大全 https:// ...

  2. php支付宝支付证书模式,,支付宝接口中的cacert.pem(ca证书)是怎么来的呢?

    小弟最近在搞支付宝支付接口,碰到个问题,help-- 我看demo中有下面一行代码: //ca证书路径地址,用于curl中ssl校验//请保证cacert.pem文件在当前文件夹目录中$alipay_ ...

  3. java SpringBoot 对接支付宝 APP支付 证书模式及非证书模式

    一. 添加maven依赖 sdk <dependency><groupId>com.alipay.sdk</groupId><artifactId>al ...

  4. 【超详细,全流程】java对接支付宝支付

    支付流程 一.对接前的准备 1.1创建应用,获取参数:APPID(使用沙箱环境可跳过) 1.1.1添加产品 1.1.2配置密钥,获取第二个参数:商户的私钥 1.1.3支付宝网关 1.1.4生成参数密钥 ...

  5. Java接入支付宝支付超级详细教程——从入门到精通

    ​ Java接入支付宝支付教程 源码下载 源码获取:点击获取源码 本文介绍了"二维码付款"的代码.其他支付方式的代码都在源码中. 一.创建应用 1.登录支付宝开放平台 支付宝开放平 ...

  6. Java接入支付宝支付教程

    Java接入支付宝支付教程 一.创建应用 1.登录支付宝开放平台 支付宝开放平台网址:https://open.alipay.com/platform/developerIndex.htm 2.创建一 ...

  7. JAVA对接支付宝支付(超详细,一看就懂)

    Java对接支付宝支付 更多内容 冷文博客: 传送门 引入 为什么要发这篇帖子呢?原因很简单,就是因为在一个稍稍正规一点的应用上都会有支付这个环节,我们日常的在线支付如今包括支付宝,微信钱包,QQ钱包 ...

  8. java对接支付宝支付

    java对接支付宝支付演示 现在有不少的项目都需要对接支付,这里主要是进行讲解对接支付宝H5支付 废话不多说 上代码 引入支付宝官方的sdk <!-- https://mvnrepository ...

  9. 最近在做支付宝支付,在本地测试一切正常,上传到服务器就遇到报错:

    最近在做支付宝支付,在本地测试一切正常,上传到服务器就遇到报错: Warning: openssl_sign() [function.openssl-sign]: Unknown signature ...

最新文章

  1. 测试一下StringBuffer和StringBuilder及字面常量拼接三种字符串的效率
  2. 《机电传动控制》学习笔记10-1
  3. java做的一个将中文转换成Unicode码的工具类【转载】做个标记,明天研究下
  4. Apache - Storm
  5. 新增或编辑保存时出错后,页面无法再次编辑
  6. 解决 spring mvc 3.0 结合 hibernate3.2 使用tx:annotation-driven声明式事务无法提交的问题(转载)...
  7. Yii 2.0 权威指南(3) 使用数据库
  8. HTML5七夕情人节表白网页(全屏七夕表白页面滚动模板) HTML+CSS+JavaScript
  9. java 枚举Enum
  10. html5 p 字号,五号字是多少pt?
  11. DVWA 不跳转_20201020好软件不私藏:稀有极品神器,直接解锁VIP!!
  12. 前端程序员应该理解的reduce方法,对你的js能力很有帮助
  13. 基于opencv的MTF算法开发
  14. 软件测试之柠檬班python全栈自动化50期测试笔记
  15. mysql同步数据_实现MySQL数据库数据的同步方法介绍
  16. 7-1 打印九九口诀表 (15分)
  17. android FDE功能介绍
  18. Picture HDU - 1828 (扫描线求矩形周长并)
  19. 【opencv】18、视频操作
  20. 安装Android应用至SD卡

热门文章

  1. 需求为纲 产品为王 极米担当行业领头羊的秘密
  2. 一种人吃蜂蜜火上浇油
  3. Windows桌面图标蓝色阴影如何去掉
  4. 4开头的5位 “时间戳“
  5. python实现推箱子
  6. 2015年第七届蓝桥杯省赛C语言B组
  7. OpenGL: 混合
  8. sin90度=1的证明
  9. ARP协议工作原理及ARP欺骗(中间人攻击)
  10. 让声音回归本质,畅听天籁之声,KZ ZEX Pro动铁发烧耳机上手实测