springboot整合微信App支付以及支付宝App支付
1. 分别导入项目依赖
<dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency><dependency><groupId>com.github.wechatpay-apiv3</groupId><artifactId>wechatpay-java</artifactId><version>0.2.17</version></dependency><dependency><groupId>com.alipay.sdk</groupId><artifactId>alipay-sdk-java</artifactId><version>4.40.272.ALL</version></dependency>
2.创建微信支付配置类(WxPayConfig),以及支付宝配置类(AliYunPayConfig)
2.1.WxPayConfig
package com.medical.config;import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAAutoCertificateConfig;
import com.wechat.pay.java.core.RSAPublicKeyConfig;
import com.wechat.pay.java.core.notification.NotificationConfig;
import lombok.Data;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;import java.io.File;@Data
@Component
public class WxPayConfig {private String appId = "wx28ac4252e8c40813";private String mchId = "1718689836";private String apiKey;private String publicKeyId = "PUB_KEY_ID_0117186898362025062500391568000000";private String privateKeyPath = "/cert/wx/apiclient_key.pem";private String publicKeyPath = "/cert/wx/pub_key.pem";private String serialNumber = "701DDAE073165BB8DC17B4B0EC398DEB0F2718C9";private String apiV3Key = "9de0e123f2124e54a4c08be458d5b44d";private String notifyUrl = "https://api.doctooi.com/medical-api/service/notify/wxpay";private String domain = "https://api.mch.weixin.qq.com/v3/pay/";private String path;@Bean("config")public Config getConfig() {// 获取当前项目路径if (path == null) {path = loadPath();}// 使用微信支付公钥的RSA配置构建器return new RSAPublicKeyConfig.Builder().merchantId(mchId).privateKeyFromPath(path + privateKeyPath).publicKeyFromPath(path + publicKeyPath).publicKeyId(publicKeyId).merchantSerialNumber(serialNumber).apiV3Key(apiV3Key).build();}private String loadPath() {path = System.getProperty("user.dir") + "/src/main/resources";File file = new File(path);if (!file.exists()) {path = System.getProperty("user.dir") + "/medical-server/src/main/resources";}return path;}
}
2.2 AliYunPayConfig
package com.medical.config;import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayAccount;
import lombok.Data;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;import java.io.File;@Component
@Data
public class AliYunPayConfig {private String appId = "2021005164622150";private String privateKey="MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCnQKma64LQN3VTFLAdx76EE/VuWcRAQZXtH09oeTu9eweCYsCzhcQmuNyl0X+rfXylwMxTkVzkBwWWVooWiggja/dUfErwrQY/L0E5OcRTMW4ZnDghz8lREcZxlAfvi/Q+cC34x3XcTudGN55LkJLZaAMI7vSqLsZSc2GDOUqS2jMgOuZ8c2Uk4grvd7giZCJQStlTF8L05S19OYy55h5bwoFZG+r0m4g2W6Kqnu0oZDIBf9U54E8KOHSGYUKC1EprPSYbllImQoi2tRMEh4RgOWTrnDfSHeYhUpbiBf+C+0vPl2Djf4my94wp0PsEsMUD4hGXNzXKFW7nET8orKM9AgMBAAECggEAQE23J832jHFWFWw1zi1WzVcTHKs8revJZdKM6ED8O/yKRZIMPrlmUfDvPH2QlXF4tA2tQU/5I96jQkrhaosFWAERpZToByKu7SoQ7JyOI+I0T3plhnJqF1Y7Mr3UU0A+1qawth6R7PMVLkUCAlGCdD3uNMgSnz++lkKwMhCb4FuMzQHf4U4/ZdPM+4kYykiCZKQPxJL89SK/nnr2WAzDNshiqyX071Ixr1f/JE92Wm61dhlogUEP1qsHIB1+qvqtO8+eORb/oHFw3LOlfOM9rHCCNSQGb2DTxPq4AIAFRc5S8wdGw+668EIKZO0IgxNtvn/RdGpXIC6b2owRQMY6jQKBgQD0XRGPgSkqe32y3fCs7SiRtMQCWGA1XA5G+D72FZWg2aZkuG8Fk4qNNaNWHl0g9iU41BeimauC8Ib55YhFfgvR8eAeUKhOyfPUO3k2Xp4k8U81bIT7U0HM1TJqZfn9W+bxUj6rts3gmPxvEpOEl6aCb5P4rgpP1hN7QSn9NeISjwKBgQCvN5E0uwmGBGcW0WMTBF7X7cRNoX6xVAoRg5S/Ow5tewB+FiX90jddWxC56AaO9qB4HhuDudLnwiqwbxPy3TTlM2dP3DBxEsJKojj24sMinn3vWaOMpKmIAx8eCO8/eDsliE6KKlongFzi4oQMplKKKr9r90okqkeWbdTZjn9jcwKBgHA8UvV7mIHHqIs//uweHXUW9rQxDTdU6cXU/W4fqdLwRMmcIHoKMyf6i+PhHFsoUx5P4+8t76W7ffNHZpisdRdfpdWmrDdL8K75Bgpf2PkU0JG0HzwkGGPRRE+0OOcSj/clFF3gH51aBw+pE5Jh6Pud7fPZVCkpJVeGLZf8aLKnAoGAKauLawD4WNj/M1wEtecaLzwqrVO077NO2a9zVq9S1RKloVbfHig6ZodbyPq3ZJSewTJX1NICqH9y65bfJakaBVBeR43UL3AIqPs/lOeFBNywkpW84ZvffatQYTI6w9tyJZDvLMi5vB849/Rq9x8vDhDwiVq8VU/xyoLAViUfgqUCgYEAyLM70mV0nG/GaJn/uuKagJbgUMSOK4DlJ01Bsid3yHwnN9mNG0kZAyfGZSKIZtaWbnAXxlldlNwTPkeGFs3iu/TKxJHRbukL5K77lain4iy0m1+1YH+4+SwnHhOloHq2EwEA9Fb/5jCbIaF6kkVcxAmg8MsIyBA/riC5btAxI0k=";private String certPath="/cert/alipay/appCertPublicKey_2021005164622150.crt";private String alipayPublicKeyPath="/cert/alipay/alipayCertPublicKey_RSA2.crt";private String alipayRootCertPath="/cert/alipay/alipayRootCert.crt";private String serverUrl = "https://openapi.alipay.com/gateway.do";private String notifyUrl = "http://t85c84dd.natappfree.cc/medical-api/service/notify/alipay";private String signType = "RSA2";private String format = "json";private String charset = "utf-8";private String path;@Beanprivate AlipayClient alipayClient() throws AlipayApiException {if(path == null) {path = loadPath();}CertAlipayRequest certAlipayRequest = new CertAlipayRequest();certAlipayRequest.setServerUrl(serverUrl);certAlipayRequest.setAppId(appId);certAlipayRequest.setPrivateKey(privateKey);certAlipayRequest.setFormat(format);certAlipayRequest.setCharset(charset);certAlipayRequest.setSignType(signType);certAlipayRequest.setCertPath(path+certPath);certAlipayRequest.setAlipayPublicCertPath(path+alipayPublicKeyPath);certAlipayRequest.setRootCertPath(path+alipayRootCertPath);return new DefaultAlipayClient(certAlipayRequest);}private String loadPath() {path = System.getProperty("user.dir") + "/src/main/resources";File file = new File(path);if (!file.exists()) {path = System.getProperty("user.dir") + "/medical-server/src/main/resources";}return path;}}
3.微信App支付实现
@Overridepublic Map<String, Object> wxAppPay(String outTradeNo) throws ServiceException {OrderInfo orderInfo = orderService.getBeanByOrderNo(outTradeNo);if (orderInfo == null) {throw new ServiceException("订单不存在");}BigDecimal payAmount = orderInfo.getPayAmount();// 将金额转换为分BigDecimal multiply = payAmount.multiply(new BigDecimal("100"));// 转换成整型Integer intValue = multiply.intValue();Integer number = orderInfo.getNumber();// 总价Integer total = intValue * number;// 订单描述String packageName = orderInfo.getPackageName();// 构建serviceAppServiceExtension service = new AppServiceExtension.Builder().config(config).build();// request.setXxx(val)设置所需参数,具体参数可见Request定义PrepayRequest request = new PrepayRequest();Amount amount = new Amount();amount.setTotal(total); // 单位分amount.setCurrency("CNY");request.setAmount(amount);request.setOutTradeNo(outTradeNo);request.setDescription(packageName);request.setNotifyUrl(wxPayConfig.getNotifyUrl());request.setAppid(wxPayConfig.getAppId());request.setMchid(wxPayConfig.getMchId());request.setNotifyUrl(wxPayConfig.getNotifyUrl());// 调用下单方法,得到应答PrepayWithRequestPaymentResponse paymentResponse = service.prepayWithRequestPayment(request);// 组装App支付参数信息Map<String, Object> appPayParams = new HashMap<>();appPayParams.put("appid", wxPayConfig.getAppId());appPayParams.put("mchid", wxPayConfig.getMchId());appPayParams.put("partner", paymentResponse.getPartnerId());appPayParams.put("prepayid", paymentResponse.getPrepayId());appPayParams.put("package", "Sign=WXPay");appPayParams.put("noncestr", paymentResponse.getNonceStr());appPayParams.put("timestamp", paymentResponse.getTimestamp());appPayParams.put("sign", paymentResponse.getSign());return appPayParams;}
4.支付宝App支付实现
@Overridepublic Map<String, Object> alipayAppPay(String orderNo) throws ServiceException {try {OrderInfo orderInfo = orderService.getBeanByOrderNo(orderNo);if (orderInfo == null) {throw new ServiceException("订单不存在");}BigDecimal payAmount = orderInfo.getPayAmount();// 将金额转换为元 1元=100分Integer number = orderInfo.getNumber();// 总价BigDecimal multiply = payAmount.multiply(new BigDecimal(number.toString()));String total = multiply.toString();// 订单描述String packageName = orderInfo.getPackageName();// 构造请求参数以调用接口AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();// 设置商户订单号model.setOutTradeNo(orderNo);// 设置订单总金额model.setTotalAmount(total);// 设置订单标题model.setSubject(packageName);// 设置产品码model.setProductCode("QUICK_MSECURITY_PAY");// 设置订单绝对超时时间,格式为yyyy-MM-dd HH:mm:ss 日历类// model.setTimeExpire("2016-12-31 10:05:00");request.setBizModel(model);request.setNotifyUrl(aliYunPayConfig.getNotifyUrl());// 调用接口,获取支付结果AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);String orderStr = response.getBody();boolean success = response.isSuccess();Map<String, Object> map = new HashMap<>();map.put("orderStr", orderStr);return map;} catch (Exception e) {throw new ServiceException("支付宝支付失败", e);}}
5.支付回调通知
package com.medical.service.impl;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.medical.config.AliYunPayConfig;
import com.medical.config.WxPayConfig;
import com.medical.model.OrderInfo;
import com.medical.service.OrderService;
import com.medical.service.PayService;
import com.shiant.rmi.exception.ServiceException;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.service.payments.app.AppServiceExtension;
import com.wechat.pay.java.service.payments.app.model.Amount;
import com.wechat.pay.java.service.payments.app.model.PrepayRequest;
import com.wechat.pay.java.service.payments.app.model.PrepayWithRequestPaymentResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;import java.math.BigDecimal;
import java.rmi.ServerException;
import java.util.HashMap;
import java.util.Map;@Service
@Slf4j
public class PayServiceImpl implements PayService {@Autowiredprivate OrderService orderService;@Autowiredprivate Config config;@Autowiredprivate WxPayConfig wxPayConfig;@Autowiredprivate AlipayClient alipayClient;@Autowiredprivate AliYunPayConfig aliYunPayConfig;@Overridepublic Map<String, Object> alipayAppPay(String orderNo) throws ServiceException {try {OrderInfo orderInfo = orderService.getBeanByOrderNo(orderNo);if (orderInfo == null) {throw new ServiceException("订单不存在");}BigDecimal payAmount = orderInfo.getPayAmount();// 将金额转换为元 1元=100分Integer number = orderInfo.getNumber();// 总价BigDecimal multiply = payAmount.multiply(new BigDecimal(number.toString()));String total = multiply.toString();// 订单描述String packageName = orderInfo.getPackageName();// 构造请求参数以调用接口AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();// 设置商户订单号model.setOutTradeNo(orderNo);// 设置订单总金额model.setTotalAmount(total);// 设置订单标题model.setSubject(packageName);// 设置产品码model.setProductCode("QUICK_MSECURITY_PAY");// 设置订单绝对超时时间,格式为yyyy-MM-dd HH:mm:ss 日历类// model.setTimeExpire("2016-12-31 10:05:00");request.setBizModel(model);request.setNotifyUrl(aliYunPayConfig.getNotifyUrl());// 调用接口,获取支付结果AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);String orderStr = response.getBody();boolean success = response.isSuccess();Map<String, Object> map = new HashMap<>();map.put("orderStr", orderStr);return map;} catch (Exception e) {throw new ServiceException("支付宝支付失败", e);}}@Overridepublic Map<String, Object> wxAppPay(String outTradeNo) throws ServiceException {OrderInfo orderInfo = orderService.getBeanByOrderNo(outTradeNo);if (orderInfo == null) {throw new ServiceException("订单不存在");}BigDecimal payAmount = orderInfo.getPayAmount();// 将金额转换为分BigDecimal multiply = payAmount.multiply(new BigDecimal("100"));// 转换成整型Integer intValue = multiply.intValue();Integer number = orderInfo.getNumber();// 总价Integer total = intValue * number;// 订单描述String packageName = orderInfo.getPackageName();// 构建serviceAppServiceExtension service = new AppServiceExtension.Builder().config(config).build();// request.setXxx(val)设置所需参数,具体参数可见Request定义PrepayRequest request = new PrepayRequest();Amount amount = new Amount();amount.setTotal(total); // 单位分amount.setCurrency("CNY");request.setAmount(amount);request.setOutTradeNo(outTradeNo);request.setDescription(packageName);request.setNotifyUrl(wxPayConfig.getNotifyUrl());request.setAppid(wxPayConfig.getAppId());request.setMchid(wxPayConfig.getMchId());request.setNotifyUrl(wxPayConfig.getNotifyUrl());// 调用下单方法,得到应答PrepayWithRequestPaymentResponse paymentResponse = service.prepayWithRequestPayment(request);// 组装App支付参数信息Map<String, Object> appPayParams = new HashMap<>();appPayParams.put("appid", wxPayConfig.getAppId());appPayParams.put("mchid", wxPayConfig.getMchId());appPayParams.put("partner", paymentResponse.getPartnerId());appPayParams.put("prepayid", paymentResponse.getPrepayId());appPayParams.put("package", "Sign=WXPay");appPayParams.put("noncestr", paymentResponse.getNonceStr());appPayParams.put("timestamp", paymentResponse.getTimestamp());appPayParams.put("sign", paymentResponse.getSign());return appPayParams;}}