Java 實現微信和支付寶支付功能

一、前期準備

1、申請好微信商戶號appid,拿到商戶id和商戶秘鑰,退款的話需要商戶證書
2、申請好支付寶商戶號appid,商戶公鑰和秘鑰(需要用支付寶工具自己生成),支付寶退款不需要證書

二、數據庫表設計

1、微信支付配置表

CREATE TABLE `py_wx_config` (
 `wx_config_id` varchar(18) NOT NULL COMMENT '微信支付配置ID',
 `appid` varchar(128) DEFAULT NULL COMMENT '微信公眾號ID',
 `mch_id` varchar(128) DEFAULT NULL COMMENT '商戶號ID',
 `mch_key_secret` varchar(2200) DEFAULT NULL COMMENT '商戶安全密鑰',
 `crt_path` varchar(200) DEFAULT NULL COMMENT '商戶證書存放路徑',
 `app_secret` varchar(2200) DEFAULT NULL COMMENT '公眾號安全密鑰',
 `create_id` varchar(18) DEFAULT NULL COMMENT '創建人',
 `create_time` datetime DEFAULT NULL COMMENT '創建時間',
 `upd_id` varchar(18) DEFAULT NULL COMMENT '修改人',
 `upd_time` datetime DEFAULT NULL COMMENT '修改時間',
 `delete_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '刪除標志',
 `app_code` varchar(18) NOT NULL COMMENT '商傢編碼',
 `bm_code` varchar(20) DEFAULT NULL COMMENT '部門編碼',
 PRIMARY KEY (`wx_config_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='微信支付配置';

2、微信小程序支付配置表

CREATE TABLE `py_wx_min_config` (
 `wx_min_config_id` varchar(18) NOT NULL COMMENT '微信支付配置ID',
 `appid` varchar(128) DEFAULT NULL COMMENT '微信公眾號ID',
 `mch_id` varchar(128) DEFAULT NULL COMMENT '商戶號ID',
 `mch_key_secret` varchar(2200) DEFAULT NULL COMMENT '商戶安全密鑰',
 `crt_path` varchar(200) DEFAULT NULL COMMENT '商戶證書存放路徑',
 `app_secret` varchar(2200) DEFAULT NULL COMMENT '公眾號安全密鑰',
 `create_id` varchar(18) DEFAULT NULL COMMENT '創建人',
 `create_time` datetime DEFAULT NULL COMMENT '創建時間',
 `upd_id` varchar(18) DEFAULT NULL COMMENT '修改人',
 `upd_time` datetime DEFAULT NULL COMMENT '修改時間',
 `delete_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '刪除標志',
 `app_code` varchar(18) NOT NULL COMMENT '商傢編碼',
 `sys_software_code` varchar(18) DEFAULT NULL COMMENT '系統編碼',
 PRIMARY KEY (`wx_min_config_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='微信支付配置';

3、支付寶支付配置表

CREATE TABLE `py_alipay_config` (
 `alipay_config_id` varchar(18) NOT NULL COMMENT '支付寶支付配置ID',
 `ali_private_key` varchar(2200) DEFAULT NULL COMMENT '支付寶密鑰',
 `ali_public_key` varchar(2200) DEFAULT NULL COMMENT '支付寶公鑰',
 `ali_appid` varchar(128) DEFAULT NULL COMMENT '支付寶appid',
 `create_id` varchar(18) DEFAULT NULL COMMENT '創建人',
 `create_time` datetime DEFAULT NULL COMMENT '創建時間',
 `upd_id` varchar(18) DEFAULT NULL COMMENT '修改人',
 `upd_time` datetime DEFAULT NULL COMMENT '修改時間',
 `delete_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '刪除標志',
 `app_code` varchar(18) NOT NULL COMMENT '商傢編碼',
 PRIMARY KEY (`alipay_config_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT COMMENT='支付寶支付配置';

4、支付流水記錄表

CREATE TABLE `py_pay_log` (
 `pay_log_id` varchar(18) NOT NULL COMMENT '支付流水ID',
 `pay_no` varchar(20) DEFAULT NULL COMMENT '支付訂單號',
 `third_id` varchar(64) DEFAULT NULL COMMENT '微信支付寶訂單ID',
 `money_type` varchar(20) DEFAULT NULL COMMENT '支付類型 0-微信 1-支付寶 2-會員卡 3-銀聯',
 `mq_topic` varchar(100) DEFAULT NULL COMMENT 'MQ主題',
 `mq_status` tinyint(3) DEFAULT NULL COMMENT 'MQ發送狀態 0-待發送 1-已發送 2-發送失敗',
 `mq_remark` varchar(100) DEFAULT NULL COMMENT 'MQ發送備註',
 `request` text COMMENT '發送數據',
 `response` text COMMENT '返回數據',
 `fee` decimal(14,2) DEFAULT NULL COMMENT '訂單金額',
 `create_id` varchar(18) DEFAULT NULL COMMENT '創建人',
 `create_time` datetime DEFAULT NULL COMMENT '創建時間',
 `upd_id` varchar(18) DEFAULT NULL COMMENT '修改人',
 `upd_time` datetime DEFAULT NULL COMMENT '修改時間',
 `delete_flag` tinyint(1) NOT NULL DEFAULT '0' COMMENT '刪除標志',
 `app_code` varchar(18) NOT NULL COMMENT '商傢編碼',
 `pay_config_json_str` longtext COMMENT '支付配置',
 PRIMARY KEY (`pay_log_id`) USING BTREE
) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC COMMENT='支付流水';

5、支付失敗記錄表

CREATE TABLE `pay_fail_log` (
 `pay_id` varchar(18) NOT NULL,
 `json_date` varchar(500) DEFAULT NULL,
 `create_id` varchar(18) DEFAULT NULL,
 `create_time` datetime DEFAULT NULL,
 `update_id` varchar(18) DEFAULT NULL,
 `update_time` datetime DEFAULT NULL,
 `app_code` varchar(18) NOT NULL,
 `delete_flag` tinyint(1) DEFAULT '0' COMMENT '是否刪除:0-否;1-是',
 PRIMARY KEY (`pay_id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=COMPACT;

三、依賴引入

 <?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

 <parent>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-parent</artifactId>
  <version>2.1.3.RELEASE</version>
  <relativePath/> <!-- lookup parent from repository -->
 </parent>

 <modelVersion>4.0.0</modelVersion>
 <groupId>com.pay</groupId>
 <artifactId>qc-payment</artifactId>
 <version>2.3</version>
 <name>qc-payment</name>
 <!-- FIXME change it to the project's website -->
 <url>http://www.example.com</url>

 <properties>
  <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  <maven.compiler.source>1.7</maven.compiler.source>
  <maven.compiler.target>1.7</maven.compiler.target>
  <spring-cloud.version>Greenwich.SR1</spring-cloud.version>
 </properties>

 <dependencies>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
  </dependency>
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
  </dependency>


  <!--z支付寶-->
  <dependency>
   <groupId>com.alipay.sdk</groupId>
   <artifactId>alipay-sdk-java</artifactId>
   <version>3.3.4.ALL</version>
  </dependency>


  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-test</artifactId>
   <scope>test</scope>
  </dependency>

  <!--導入重試機制的坐標-->
  <dependency>
   <groupId>org.springframework.retry</groupId>
   <artifactId>spring-retry</artifactId>
  </dependency>

  <!--引入Hystrix依賴-->
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  </dependency>

  <!--導入jwt相關依賴-->
  <dependency>
   <groupId>com.auth0</groupId>
   <artifactId>java-jwt</artifactId>
   <version>3.4.1</version>
  </dependency>

  <!-- StringUtil 類-->
  <dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
   <version>3.3.2</version>
  </dependency>

  <!-- ali 連接池 -->
  <dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>druid</artifactId>
   <version>1.1.12</version>
  </dependency>

  <!-- mybatis -->
  <dependency>
   <groupId>org.mybatis.spring.boot</groupId>
   <artifactId>mybatis-spring-boot-starter</artifactId>
   <version>2.0.0</version>
  </dependency>

  <!-- mysql -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
  </dependency>
  <dependency>
   <groupId>javax.persistence</groupId>
   <artifactId>persistence-api</artifactId>
   <version>1.0.2</version>
  </dependency>
  <!-- https://mvnrepository.com/artifact/tk.mybatis/mapper -->
  <dependency>
   <groupId>tk.mybatis</groupId>
   <artifactId>mapper</artifactId>
   <version>4.0.3</version>
  </dependency>

  <!-- import lombok 可以省去getter setter toString等方法 -->
  <dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <scope>provided</scope>
  </dependency>

  <!-- commons-io -->
  <dependency>
   <groupId>commons-io</groupId>
   <artifactId>commons-io</artifactId>
   <version>2.4</version>
  </dependency>

  <!-- 引入easyqinyu-tools項目 -->
  <dependency>
   <groupId>com.pay</groupId>
   <artifactId>easyqinyu-tools</artifactId>
   <version>0.0.1-SNAPSHOT</version>
  </dependency>

  <!-- pagehelper分頁插件 -->
  <dependency>
   <groupId>com.github.pagehelper</groupId>
   <artifactId>pagehelper</artifactId>
   <version>5.1.2</version>
  </dependency>

  <dependency>
   <groupId>com.github.pagehelper</groupId>
   <artifactId>pagehelper-spring-boot-autoconfigure</artifactId>
   <version>1.2.3</version>
  </dependency>
  <dependency>
   <groupId>com.github.pagehelper</groupId>
   <artifactId>pagehelper-spring-boot-starter</artifactId>
   <version>1.2.3</version>
  </dependency>
  <dependency>
   <groupId>com.qcsoft</groupId>
   <artifactId>qc-swagger-ui</artifactId>
   <version>0.0.1-SNAPSHOT</version>
   <scope>compile</scope>
  </dependency>
  <dependency>
   <groupId>com.google.zxing</groupId>
   <artifactId>core</artifactId>
   <version>3.3.0</version>
  </dependency>

  <dependency>
   <groupId>com.alibaba</groupId>
   <artifactId>fastjson</artifactId>
   <version>RELEASE</version>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>org.apache.httpcomponents</groupId>
   <artifactId>httpclient</artifactId>
   <version>${httpclient.version}</version>
  </dependency>


  <dependency>
   <groupId>com.google.code.gson</groupId>
   <artifactId>gson</artifactId>
   <version>2.8.2</version>
  </dependency>


  <!--阿裡雲信息發送-->
  <dependency>
   <groupId>com.aliyun</groupId>
   <artifactId>aliyun-java-sdk-core</artifactId>
   <version>3.3.1</version>
  </dependency>
  <dependency>
   <groupId>com.github.1991wangliang</groupId>
   <artifactId>aliyun-java-sdk-dysmsapi</artifactId>
   <version>1.0.0</version>
  </dependency>

  <dependency>
   <groupId>org.springframework.kafka</groupId>
   <artifactId>spring-kafka</artifactId>
  </dependency>

  <!-- xml解析-->
  <dependency>
   <groupId>com.thoughtworks.xstream</groupId>
   <artifactId>xstream</artifactId>
   <version>1.4.10</version>
  </dependency>

  <!-- dom4j -->
  <dependency>
   <groupId>org.dom4j</groupId>
   <artifactId>dom4j</artifactId>
   <version>2.1.1</version>
  </dependency>

   <dependency>
   <groupId>com.github.binarywang</groupId>
   <artifactId>weixin-java-common</artifactId>
   <version>3.3.4.B</version>
  </dependency>


  <dependency>
   <groupId>org.jodd</groupId>
   <artifactId>jodd-http</artifactId>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>org.apache.commons</groupId>
   <artifactId>commons-lang3</artifactId>
  </dependency>


  <!-- xml解析-->
  <dependency>
   <groupId>commons-beanutils</groupId>
   <artifactId>commons-beanutils</artifactId>
   <version>1.9.3</version>
  </dependency>

  <dependency>
   <groupId>jdom</groupId>
   <artifactId>jdom</artifactId>
   <version>1.0</version>
  </dependency>


  <dependency>
   <groupId>org.bouncycastle</groupId>
   <artifactId>bcpkix-jdk15on</artifactId>
   <version>1.59</version>
  </dependency>
  <dependency>
   <groupId>org.jodd</groupId>
   <artifactId>jodd-http</artifactId>
   <version>3.7.1</version>
  </dependency>
  <!--二維碼工具-->
  <dependency>
   <groupId>com.google.zxing</groupId>
   <artifactId>core</artifactId>
   <version>3.2.1</version>
  </dependency>

  <dependency>
   <groupId>com.qcsoft</groupId>
   <artifactId>qc-commonbean</artifactId>
   <version>0.0.1-SNAPSHOT</version>
  </dependency>

  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>
  <!-- xxl-job-core -->
  <dependency>
   <groupId>com.xuxueli</groupId>
   <artifactId>xxl-job-core</artifactId>
   <version>2.0.1</version>
  </dependency>
  <!--線路跟蹤-->
  <dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
  </dependency>

  <dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-actuator</artifactId>
  </dependency>
 </dependencies>


 <dependencyManagement>
  <dependencies>
   <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>${spring-cloud.version}</version>
    <type>pom</type>
    <scope>import</scope>
   </dependency>
  </dependencies>
 </dependencyManagement>
 <build>
  <finalName>qc-payment</finalName>
  <plugins>
   <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
   </plugin>
   <plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
     <source>8</source>
     <target>8</target>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>

四、程序實現

1、Controller

package com.qcsoft.payment.controller;

import com.alibaba.fastjson.JSON;
import com.qcsoft.commonbean.bean.common.SwaggerConstant;
import com.qcsoft.commonbean.bean.payment.common.PrePayResult;
import com.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
import com.qcsoft.commonbean.bean.payment.wx.exception.WxPayException;
import com.qcsoft.commonbean.bean.payment.wx.util.QrcodeUtils;
import com.qcsoft.easyqinyutools.message.ReturnMsg;
import com.qcsoft.payment.controller.commom.BaseController;
import com.qcsoft.payment.service.PayService;
import com.qcsoft.swaggerui.anno.ApiTag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.IOException;


/**
 * @Description: 支付控制中心
 * @Author: 
 * @Date: 
 */
@RestController
@RequestMapping("/v2")
public class PayController extends BaseController {
 private static final Logger logger = LoggerFactory.getLogger(PayController.class);

 @Autowired
 private PayService payService;

 //private final AtomicInteger tick = new AtomicInteger();

 /**
  * 統一預支付接口(統一下單)
  *
  * @param orderParam {dh:訂單號,payType:支付方式(WXPAY、ALIPAY、MEMBER_CARD、ACCOUNT),appCode:商傢編碼,
  *     tradeType:支付方式類型(NATIVE、JSAPI、APP、MWEB),openId:支付方式為JSAPI必傳,reqId:請求的真實IP地址
  *     ,redirectUrl:支付成功返回地址,appCode:商傢編碼,outTradeNo:商務訂單號,timeExpire,訂單到期時間
  *     ,totalAmount:訂單金額,body:商品簡單描述,subject:訂單標題,quitUrl:中途退出}
  * @param token  token
  * @return (微信公眾號 / 小程序返回一串json字符串 : { appId :, timeStamp :, nonceStr : , info_package :, paySign :, signType : }, 前端使用微信sdk調用微信支付)
  * (微信掃碼支付返回一個連接,前端需要把連接生成一個二維碼使用,連接如:weixin://123.123.com/***)
  * (微信H5--返回一個連接,前端需要把連接生成一個連接前端直接跳轉該連接使用,使用如:location.href='weixin://123.123.com/***')
  * (支付寶掃碼支付--返回一個連接,前端直接跳轉到該連接使用,使用如:location.href='weixin://123.123.com/***')
  * (支付寶掃碼H5--返回一個頁面form表單,前端需要把這個form表單渲染到h5頁面上,使用如:$("#view).html(alipayForm)')
  * (支付寶app支付--返回一個參數包,如sdk-version=**&service=**&&service=**&&body=**&&out_trade_no=**&,前端使用支付寶sdk調用app支付')
  * {
  * wxNativeUrl:微信掃碼地址
  * wxAppPackage:app支付sdk參數包
  * wxJsapiPackage:公眾號支付包
  * wxH5Url:h5支付url
  * wxScanUrl:wxScanUrl
  * alipayScanUrl:支付寶掃碼支付url
  * alipayH5Form:支付寶h5支付表單
  * alipayAppParamStr:支付寶app支付參數支付串
  * }
  * @throws WxPayException
  */
 @RequestMapping(value = "/prePayOrder")
 @ApiTag(SwaggerConstant.PAYMENT_001)
 public ReturnMsg prePayOrder(@RequestBody PreOrderParam orderParam) {
  String metadata = JSON.toJSONString(orderParam);
  logger.info("PayController.prePayOrder----\n正在請求支付....,參數為>>>>{}", metadata);
  ReturnMsg ret = new ReturnMsg();
  //預下單
  PrePayResult prePayResult = this.payService.payPreOrder(orderParam);
  ret.setData(prePayResult);
  return ret.success("下單成功,訂單有效期為" + orderParam.getTimeExpire());
 }

 /**
  * 生成支付二維碼
  *
  * @param url 二維碼地址
  * @throws IOException
  */
 @RequestMapping(value = "/createQrCode/url")
 @ApiTag(SwaggerConstant.PAYMENT_001)
 public void createQrCode(@PathVariable String url, HttpServletRequest request, HttpServletResponse response) throws IOException {
  String queryString = request.getQueryString();
  BufferedImage bufferedImage = QrcodeUtils.encode(url+queryString, 500, 500, null, null);
  BufferedImage grayImage = QrcodeUtils.grayImage(bufferedImage);
  ImageIO.write(grayImage, "png", response.getOutputStream());
 }


}

2、PayService

package com.qcsoft.payment.service.impl;

import com.alibaba.fastjson.JSON;
import com.alipay.api.AlipayClient;
import com.qcsoft.commonbean.bean.common.KafkaConstant;
import com.qcsoft.commonbean.bean.payment.ChinaumsConfig;
import com.qcsoft.commonbean.bean.payment.PayLog;
import com.qcsoft.commonbean.bean.payment.common.PayConstant;
import com.qcsoft.commonbean.bean.payment.common.PrePayResult;
import com.qcsoft.commonbean.bean.payment.common.WxPrePayResultPackage;
import com.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
import com.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayUnifiedOrderRequest;
import com.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayUnifiedOrderResult;
import com.qcsoft.commonbean.bean.payment.wx.config.WxPayConfig;
import com.qcsoft.easyqinyutools.utils.JsonUtil;
import com.qcsoft.payment.commns.exception.BaseException;
import com.qcsoft.payment.commns.exception.QYError;
import com.qcsoft.payment.commns.utils.UserUtil;
import com.qcsoft.payment.commns.utils.weixin.PackageUtil;
import com.qcsoft.payment.service.*;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.SortedMap;
import java.util.TreeMap;

@Service
public class PayServiceImpl implements PayService {
 public Logger logger = LoggerFactory.getLogger(getClass());
 @Autowired
 private AliPayService aliPayService;
 @Autowired
 private WxPayService wxPayService;
 @Autowired
 private ChinaumsPayService chinaumsPayService;

 @Autowired
 private UserUtil userUtil;
 @Autowired
 private PayLogService payLogService;


 @Override
 public PrePayResult payPreOrder(PreOrderParam orderParam) throws BaseException {
  logger.info("PayServiceImpl.payPreOrder---->>>>\n準備下單.....,當前用戶訂單號[{}]", orderParam.getDh());
  String temp = "";
  PrePayResult payResult = new PrePayResult();
  //校驗支付方式
  String payType = orderParam.getPayType();
  if (!StringUtils.isNotBlank(payType))
   throw new BaseException(QYError.msg("請選擇支付方式!"));
  if (PayConstant.WXPAY.toString().equals(payType)) {
   //查詢商傢配置信息
   WxPayConfig config;
   if (orderParam.getTradeType().equals(PayConstant.WECHATAPP.toString())) {
    config = wxPayService.getWxMinPayConfigByAppCode(orderParam.getAppCode(), orderParam.getSysSoftwareCode());
   } else {
    config = wxPayService.getWxPayConfigByAppCode(orderParam.getAppCode(), orderParam.getBmCode());
   }
   //設置預支付請求參數
   if (orderParam.getTradeType().equals(PayConstant.WECHATAPP.toString())) {
    orderParam.setTradeType(PayConstant.JSAPI.toString());
   }
   WxPayUnifiedOrderRequest requestParam = wxPayService.packRequestParam(orderParam);
   //開始請求預支付接口
   WxPayUnifiedOrderResult result = wxPayService.wxPrePay(config, requestParam);
   //根據支付類型設置值
   WxPrePayResultPackage resultPackage = null;
   if (orderParam.getTradeType().equals(PayConstant.APP.toString()) || orderParam.getTradeType().equals(PayConstant.JSAPI.toString()) || orderParam.getTradeType().equals(PayConstant.WECHATAPP.toString())) {
    resultPackage = new WxPrePayResultPackage();
    String timeMillis = PackageUtil.getTimeStamp();
    String nonceString = PackageUtil.getNonceStr();
    resultPackage.setAppId(result.getAppid());
    resultPackage.setNonceStr(nonceString);
    resultPackage.setTimeStamp(timeMillis);
    resultPackage.setPrePayId(result.getPrepayId());
    resultPackage.setInfoPackage("prepay_id=" + result.getPrepayId());
    resultPackage.setSignType(requestParam.getSignType());
    if (orderParam.getTradeType().equals(PayConstant.APP.toString())) {
     SortedMap<String, String> returnData = PackageUtil.getReturnData(resultPackage, config.getMchId());
     String paysign = PackageUtil.createSign(returnData, config.getMchKey());
     resultPackage.setPaySign(paysign);
     resultPackage.setInfoPackage(returnData.get("package"));
     payResult.setWxAppPackage(resultPackage);
    } else {
     SortedMap<String, String> paypackageParams = new TreeMap<String, String>();
     paypackageParams.put("appId", result.getAppid()); // appid
     paypackageParams.put("timeStamp", timeMillis); //
     paypackageParams.put("nonceStr", nonceString); //
     paypackageParams.put("package", resultPackage.getInfoPackage()); //
     paypackageParams.put("signType", resultPackage.getSignType());
     String paysign = PackageUtil.createSign(paypackageParams, config.getMchKey());
     resultPackage.setPaySign(paysign);
     payResult.setWxJsapiPackage(resultPackage);
    }
   } else if (orderParam.getTradeType().equals(PayConstant.MWEB.toString())) {
    payResult.setWxH5Url(result.getMwebUrl() + " &redirect_url=" + orderParam.getRedirectUrl());
   } else if (orderParam.getTradeType().equals(PayConstant.NATIVE.toString())) {
    payResult.setWxNativeUrl(result.getCodeURL());
   }
   //添加支付日志
   insertPayLog(orderParam, KafkaConstant.PAYMENT_NOTIFY_001.getTopic(), "0", resultPackage, JSON.toJSONString(config));
   return payResult;
  } else if (PayConstant.ALIPAY.toString().equals(payType)) {
   AlipayClient client = aliPayService.getAlipayClientByAppCode(orderParam.getAppCode());
   if (orderParam.getTradeType().equals(PayConstant.APP.toString())) {
    temp = aliPayService.aliAppPay(client, orderParam);
    payResult.setAlipayAppParamStr(temp);
   } else if (orderParam.getTradeType().equals(PayConstant.MWEB.toString())) {
    temp = aliPayService.aliH5Pay(client, orderParam);
    payResult.setAlipayH5Form(temp);
   } else if (orderParam.getTradeType().equals(PayConstant.NATIVE.toString())) {
    temp = aliPayService.aliScanPay(client, orderParam);
    payResult.setAlipayScanUrl(temp);
   }
   //添加支付日志
   insertPayLog(orderParam, KafkaConstant.PAYMENT_NOTIFY_001.getTopic(), "1", orderParam, JSON.toJSONString(aliPayService.getConfigByAppCode(orderParam.getAppCode())));
   return payResult;
  } else if (PayConstant.WECHATAPP.toString().equals(payType)) {

  } else if (PayConstant.CHINAUMS.toString().equals(payType)) { //銀聯pos支付
   //查詢商傢配置信息
   ChinaumsConfig config;
   config = chinaumsPayService.getPayConfigByAppCode(orderParam.getAppCode(), orderParam.getBmCode());
   if (orderParam.getTradeType().equals(PayConstant.CODE_SCAN.toString())) {
    chinaumsPayService.codeScanPay(config, orderParam);
   }
   //添加支付日志
   insertPayLog(orderParam, KafkaConstant.PAYMENT_NOTIFY_001.getTopic(), "3", orderParam, JSON.toJSONString(config));
   return payResult;
  }
  logger.warn("用戶未選擇正確的支付方式");
  throw new BaseException(QYError.msg("請選擇正確的支付方式!"));

 }

 public void insertPayLog(PreOrderParam orderParam, String topic, String moneyType, Object obj, String payConfigJsonStr) {
  PayLog payLog = new PayLog();
  payLog.setAppCode(orderParam.getAppCode());
  payLog.setPayLogId(orderParam.getDh());
  payLog.setMoneyType(moneyType);
  payLog.setMqTopic(topic);
  payLog.setMqStatus(0);
  payLog.setPayNo(orderParam.getDh());
  payLog.setRequest(JsonUtil.toJSon(obj));
  payLog.setFee(orderParam.getTotalAmount());
  payLog.setPayConfigJsonStr(payConfigJsonStr);
  payLogService.saveOrUpdate(payLog);
 }
}

3、AliPayService

package com.qcsoft.payment.service;

import com.alipay.api.AlipayClient;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.qcsoft.commonbean.bean.payment.AlipayConfig;
import com.qcsoft.commonbean.bean.payment.alipay.AliPayRefundParam;
import com.qcsoft.commonbean.bean.payment.common.PayNotify;
import com.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
import com.qcsoft.easyqinyutools.message.ReturnMsg;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

public interface AliPayService {
 /**
  *
  * @param alipayClient
  * @param orderParam
  * @param
  * @return
  */
 String aliAppPay(AlipayClient alipayClient,PreOrderParam orderParam);


 String aliScanPay(AlipayClient alipayClient, PreOrderParam orderParam);

 String aliH5Pay(AlipayClient alipayClient, PreOrderParam orderParam);

 void aliPayNotify(PayNotify params);

 boolean rsaCheckV1(HttpServletRequest request,String appCode);

 AlipayTradeQueryResponse aliPayOrderQuery(AlipayClient alipayClient, String out_trade_no);

 AlipayClient getAlipayClientByAppCode(String appCode);

 AlipayConfig getConfigByAppCode(String appCode);

 /**
  * 支付寶退款接口
  * @param aliPayRefundParam
  * @return
  */
 ReturnMsg aliPayRefund(AliPayRefundParam aliPayRefundParam);

}

AliPayServiceImpl

package com.qcsoft.payment.service.impl;

import com.alibaba.fastjson.JSON;
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.domain.AlipayTradePrecreateModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import com.qcsoft.commonbean.bean.payment.AlipayConfig;
import com.qcsoft.commonbean.bean.payment.alipay.AliPayRefundParam;
import com.qcsoft.commonbean.bean.payment.common.PayConstant;
import com.qcsoft.commonbean.bean.payment.common.PayNotify;
import com.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
import com.qcsoft.easyqinyutools.message.ReturnMsg;
import com.qcsoft.payment.commns.exception.BaseException;
import com.qcsoft.payment.commns.exception.QYError;
import com.qcsoft.payment.commns.utils.DateUtils;
import com.qcsoft.payment.commns.utils.RedisUtil;
import com.qcsoft.payment.service.AliPayService;
import com.qcsoft.payment.service.AlipayConfigService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletRequest;
import java.net.URLEncoder;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
 * 支付寶相關業務實現類
 */
@Service
public class AliPayServiceImpl implements AliPayService {
 private static final Logger logger = LoggerFactory.getLogger(AliPayServiceImpl.class);
 @Autowired
 private AlipayConfigService alipayConfigService;
 @Autowired
 private RedisUtil redisUtil;
 @Value("${payNotifyUrl}")
 private String notifyUrl;

 /**
  * APP支付
  * 參數加簽
  */
 @Override
 public String aliAppPay(AlipayClient alipayClient, PreOrderParam orderParam) {
  logger.info("AliPayServiceImpl.aliAppPay--->>>\n支付寶預支付開始,\n支付類型為:APP支付,\n訂單號為:{}", orderParam.getDh());
  Date date = new Date();
  AlipayTradeAppPayResponse response = null;
  // 發起App支付請求
  AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
  // 訂單描述
  model.setBody(orderParam.getBody());
  // 訂單標題
  model.setSubject(orderParam.getSubject());
  // 商戶訂單號 就是商戶後臺生成的訂單號
  model.setOutTradeNo(orderParam.getOutTradeNo());
  // 該筆訂單允許的最晚付款時間,逾期將關閉交易。取值范圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天 (屁股後面的字母一定要帶,不然報錯)
  model.setTimeoutExpress(DateUtils.toString(date, orderParam.getTimeExpire()));
  // 訂單總金額 ,默認單位為元,精確到小數點後兩位,取值范圍[0.01,100000000]
  model.setTotalAmount(orderParam.getTotalAmount().toString());
  // 銷售產品碼
  model.setProductCode(PayConstant.ALIPAY_QUICK_WAP_WAY.getKey());
  AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
  request.setBizModel(model);
  // request.setNotifyUrl("商戶外網可以訪問的異步地址,不寫就是不回調");
  request.setNotifyUrl(notifyUrl + PayConstant.ALIPAY_05.getKey() + "/" + orderParam.getAppCode() + "/" + orderParam.getDh());
  //支付成功返回地址
  request.setReturnUrl(orderParam.getRedirectUrl());
  // 通過api的方法請求阿裡接口獲得反饋
  logger.info("AliPayServiceImpl.aliAppPay----->\n支付寶預支付接口請求信息:{}", JSON.toJSONString(request));
  try {
   response = alipayClient.sdkExecute(request);
  } catch (AlipayApiException e) {
   logger.info("AliPayServiceImpl.aliAppPay----->\n支付寶預下單失敗,\n本次下單的訂單號為:{},\n相關報錯信息為:{}", orderParam.getDh(), response, e);
   throw new BaseException(QYError.msg("調用支付寶預下單接口失敗![" + e.getMessage() + "]"));
  }

  logger.info("AliPayServiceImpl.aliAppPay----->\n支付寶預支付接口返回信息:{}", JSON.toJSONString(response));
  if (response.isSuccess()) {
   logger.info("AliPayServiceImpl.aliAppPay----->\n支付寶預下單成功,\n本次下單的訂單號為:{},商戶訂單號為:{}", orderParam.getDh(), orderParam.getOutTradeNo());
  } else {
   logger.error("AliPayServiceImpl.aliAppPay----->\n調用支付寶預下單接口失敗!\n具體信息為:\n{}", response.getBody());
   throw new BaseException(QYError.msg("調用支付寶預下單接口失敗![" + response.getMsg() + "]"));
  }
  return response.getBody();
 }


 /**
  * 掃碼支付
  * 參數加簽
  */
 @Override
 public String aliScanPay(AlipayClient alipayClient, PreOrderParam orderParam) {
  logger.info("AliPayServiceImpl.aliScanPay--->>>\n支付寶預支付開始,\n支付類型為:掃碼支付,\n訂單號:{}", orderParam.getDh());
  /* AlipayTradePagePayResponse response = null;*/
  AlipayTradePrecreateResponse response = null;
  Date date = new Date();
  /**
   * 設置請求model參數(body、subject、outTradeNo、totalAmount、timeoutExpress;必傳)
   */
  AlipayTradePrecreateModel model = new AlipayTradePrecreateModel();
  // 訂單描述
  model.setBody(orderParam.getBody());
  // 訂單標題
  model.setSubject(orderParam.getBody());
  // 商戶訂單號 就是商戶後臺生成的訂單號
  model.setOutTradeNo(orderParam.getOutTradeNo());
  // 該筆訂單允許的最晚付款時間,逾期將關閉交易。取值范圍:1m~15d。m-分鐘,h-小時,d-天,1c-當天 (屁股後面的字母一定要帶,不然報錯)
  model.setTimeoutExpress(orderParam.getTimeExpire());
  //model.setSellerId(DateUtils.toString(date, "yyyyMMddHHmmssSSS"));
  // 訂單總金額 ,默認單位為元,精確到小數點後兩位,取值范圍[0.01,100000000]
  model.setTotalAmount(orderParam.getTotalAmount().toString());
  //model.setProductCode(PayConstant.ALIPAY_FAST_INSTANT_TRADE_PAY.getKey());
  // 選填
  /**
   * 創建支付寶掃碼支付請求接口類,設置相關請求處理信息,準備請求下單
   */
  AlipayTradePrecreateRequest request = new AlipayTradePrecreateRequest();
  request.setBizModel(model);
  // request.setNotifyUrl("商戶外網可以訪問的異步地址,不寫就是不回調");
  request.setNotifyUrl(notifyUrl + PayConstant.ALIPAY_05.getKey() + "/" + orderParam.getAppCode() + "/" + orderParam.getDh());

  //支付成功返回地址
  request.setReturnUrl(orderParam.getRedirectUrl());
  // 通過api的方法請求阿裡接口獲得反饋 alipayClient.pageExecute(request)
  try {
   logger.info("支付寶掃碼付請求報文:{}",JSON.toJSONString(request));
   response = alipayClient.execute(request)/**/;
  } catch (AlipayApiException e) {
   logger.info("AliPayServiceImpl.aliScanPay----->\n支付寶預下單失敗,\n本次下單的訂單號:{},\n相關報錯信息為:{}", orderParam.getDh(), response, e);
   throw new BaseException(QYError.msg("調用支付寶預下單接口失敗![" + e.getMessage() + "]"));
  }catch (Exception e){
   e.printStackTrace();
   throw new BaseException(QYError.msg("調用支付寶預下單接口失敗![" + e.getMessage() + "]"));
  }

  //打印返回信息
  logger.info("AliPayServiceImpl.aliScanPay----->\n支付寶預支付接口返回信息:{}", JSON.toJSONString(response));
  //判斷預下單返回狀態
  if (response.isSuccess()) {
   logger.info("AliPayServiceImpl.aliScanPay----->\n支付寶預下單成功,\n本次下單的訂單號:{},商務訂單號為", orderParam.getDh(), orderParam.getOutTradeNo());
  } else {
   logger.error("AliPayServiceImpl.aliScanPay----->\n調用支付寶預下單接口失敗!\n具體信息:\n{}", response.getBody());
   throw new BaseException(QYError.msg("調用支付寶預下單接口失敗![" + response.getMsg() + "]"));
  }

  return response.getQrCode();
 }


 /**
  * H5支付
  * 參數加簽
  */
 @Override
 public String aliH5Pay(AlipayClient alipayClient, PreOrderParam orderParam) {
  logger.info("AliPayServiceImpl.aliH5Pay--->>>\n支付寶預支付開始,\n支付類型為:H5支付,\n訂單號:{}", orderParam.getDh());
  String form = "";
  AlipayTradeWapPayResponse response = null;
  /**
   * 封裝請求支付信息
   */
  AlipayTradeWapPayModel payModel = new AlipayTradeWapPayModel();
  payModel.setOutTradeNo(orderParam.getOutTradeNo());
  payModel.setSubject(orderParam.getBody());
  payModel.setTotalAmount(orderParam.getTotalAmount().toString());
  payModel.setBody(orderParam.getBody());
  payModel.setTimeoutExpress(orderParam.getTimeExpire());
  payModel.setProductCode(PayConstant.ALIPAY_QUICK_WAP_WAY.getKey());
  payModel.setQuitUrl(URLEncoder.encode(orderParam.getQuitUrl()));
  /**
   * 創建支付寶H5支付請求接口類,設置相關請求處理信息,準備請求下單
   */
  AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();
  alipay_request.setBizModel(payModel);
  // 設置異步通知地址
  logger.info("通知地址{}", notifyUrl + PayConstant.ALIPAY_05.getKey() + "/" + orderParam.getAppCode() + "/" + orderParam.getDh());
  alipay_request.setNotifyUrl(notifyUrl + PayConstant.ALIPAY_05.getKey() + "/" + orderParam.getAppCode() + "/" + orderParam.getDh());
  // 設置同步地址
  alipay_request.setReturnUrl(URLEncoder.encode(orderParam.getRedirectUrl()));
  // 調用SDK生成表單
  try {
   response = alipayClient.pageExecute(alipay_request);
   if (response.isSuccess()) {
    form = response.getBody();
    logger.info("AliPayServiceImpl.aliH5Pay----->>>>\n支付寶預支付接口返回信息:{}", JSON.toJSONString(response));
   } else {
    logger.info("AliPayServiceImpl.aliH5Pay----->>>>\n支付寶預支付接口返回信息:{}", JSON.toJSONString(response));
    throw new BaseException(QYError.msg("支付寶"));
   }

  } catch (AlipayApiException e) {
   logger.info("AliPayServiceImpl.aliH5Pay----->>>>\n支付寶預支付接口返回信息:{}", JSON.toJSONString(response));
   throw new BaseException(QYError.msg("調用支付寶預下單接口失敗![" + e.getMessage() + "]"));
  }
  logger.info("AliPayServiceImpl.aliH5Pay----->>>>\n支付寶預支付接口返回信息:{}", JSON.toJSONString(response));
  /**
   * 打印日志,並返回鏈接
   */
  return form;
 }

 /**
  * 支付寶通知
  *
  * @param params
  */
 @Override
 public void aliPayNotify(PayNotify params) {
  logger.info("AliPayServiceImpl.appAliPayNotify-\n阿裡服務器消費手機回調參數獲取和參數判斷-------》》》");
  /**
   * 打印信息
   */
  //校驗支付金額
  /*ReturnMsg returnMsg = restTemplate.postForEntity(params.getNoOrderAmountUrl(), params, ReturnMsg.class).getBody();
  if (!returnMsg.isSuccess()) {
   logger.info("WxPayController.wxPayNotify-->\n校驗訂單金額失敗,請核實商務訂單號:{}", params);
   throw new BaseException(QYError.msg("校驗訂單金額失敗!商務訂單號[" + params.getOutTradeNo() + "]"));
  }*/
  /**
   * 判斷支付狀態
   */
  if (params.getTradeStatus().equals("TRADE_SUCCESS")) {
   logger.info("AliPayServiceImpl.appAliPayNotify----\n支付寶支付成功!商務訂單號[{}]----->>", params.getOutTradeNo(), JSON.toJSONString(params));
  } else {
   logger.error("AliPayServiceImpl.appAliPayNotify---\n支付寶支付失敗!商務訂單號[{}]---->>", params.getOutTradeNo());
   throw new BaseException(QYError.msg("支付寶支付失敗!商務訂單號[" + params.getOutTradeNo() + "]"));
  }
 }

 @Override
 public boolean rsaCheckV1(HttpServletRequest request, String appCode) {
  //獲取支付寶GET過來反饋信息
  Map<String, String> params = new HashMap<String, String>();
  // 簽名驗證(對支付寶返回的數據驗證,確定是支付寶返回的)
  boolean result = false;
  try {
   // 從支付寶回調的request域中取值
   Map<String, String[]> requestParams = request.getParameterMap();
   for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
    String name = 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] + ",";
    }
    params.put(name, valueStr);
   }
   logger.info("AliPayServiceImpl.appAliPayNotify--\n支付寶通知數據包----->>>>>>>>>>>>>>>{}", JSON.toJSONString(params));
   // 商傢編碼

   AlipayConfig alipayConfig = getConfigByAppCode(appCode);
   result = AlipaySignature.rsaCheckV1(params, alipayConfig.getAliPublicKey(),
     PayConstant.ALIPAY_CHARSET.getKey(), PayConstant.ALIPAY_SIGN_TYPE_RSA2.getKey());
  } catch (Exception e) {
   logger.error("AliPayServiceImpl.appAliPayNotify---\n校驗簽名失敗!商務訂單號[{}]---->>", JSON.toJSONString(request), e);
   throw new BaseException(QYError.msg("支付寶支付校驗簽名失敗!"));
  }
  return result;
 }

 /**
  * 根據商務訂單號查詢查詢支付信息
  *
  * @param alipayClient
  * @param out_trade_no
  * @return
  */
 @Override
 public AlipayTradeQueryResponse aliPayOrderQuery(AlipayClient alipayClient, String out_trade_no) {
  logger.info("AliPayServiceImpl.aliPayOrderQuery----\n根據商務訂單號查詢支付寶訂單信息,\n商務訂單號:[{}]----》》》", out_trade_no);
  AlipayTradeQueryResponse response = null;
  AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
  //設置查詢參數
  Map<String, String> bizModel = new HashMap<>();
  bizModel.put("out_trade_no", out_trade_no);
  request.setBizContent(JSON.toJSONString(bizModel));
  //開始查詢
  try {
   response = alipayClient.execute(request);
  } catch (AlipayApiException e) {
   logger.error("AliPayServiceImpl.aliPayOrderQuery--->>\n支付寶訂單查詢失敗,\n商務訂單號:[{}]", out_trade_no);
   throw new BaseException(QYError.msg("訂單號[" + out_trade_no + "],訂單支付失敗,狀態碼為[" + response.getTradeStatus() + "]"));
  }

  logger.info("AliPayServiceImpl.aliPayOrderQuery---->>\n查詢支付寶訂單信息,\n商務訂單號:[{}],\n返回信息:{}", out_trade_no, JSON.toJSONString(response));
  //查詢狀態處理
  if (response.isSuccess()) {
   logger.info("AliPayServiceImpl.aliPayOrderQuery--->>\n支付寶訂單查詢成功,\n商務訂單號:[{}]", out_trade_no);
  } else {
   logger.error("AliPayServiceImpl.aliPayOrderQuery--->>\n支付寶訂單查詢失敗,\n商務訂單號:[{}]", out_trade_no);
   throw new BaseException(QYError.msg("訂單號[" + out_trade_no + "],訂單支付失敗,狀態碼為[" + response.getTradeStatus() + "]"));
  }

  return response;
 }


 /**
  * 根據商傢編碼設置alipay配置信息
  *
  * @param appCode 商傢編碼
  * @return
  */
 @Override
 public AlipayClient getAlipayClientByAppCode(String appCode) {
  logger.info("AliPayServiceImpl.getAlipayClientByAppCode--->>\n獲取支付寶配置信息:[{}]", appCode);
  AlipayConfig alipayConfig = null;
  /**
   * 獲取商傢支付寶配置信息(優先級:1-redis,2-mysql,3-用戶系統)
   */
  try {
   alipayConfig = getConfigByAppCode(appCode);
   if (alipayConfig == null) {
    logger.info("AliPayServiceImpl.getAlipayClientByAppCode--->>\n獲取支付寶支付配置信息失敗:[{}]", appCode);
    logger.info("AliPayServiceImpl.getAlipayClientByAppCode--->>\n獲取支付寶支付配置信息失敗:[{}{}]", appCode,alipayConfig);
    throw new BaseException(QYError.msg("獲取支付寶支付配置信息失敗!"));
   }
  } catch (Exception e) {
   logger.error("AliPayServiceImpl.getAlipayClientByAppCode--->>\n獲取支付寶配置信息失敗:[{}]", e);
   throw new BaseException(QYError.msg("獲取支付寶配置信息失敗!"));
  }
  AlipayClient alipayClient = new DefaultAlipayClient(
    PayConstant.ALIPAY_01.getKey(),
    alipayConfig.getAliAppid(),
    alipayConfig.getAliPrivateKey(),
    PayConstant.ALIPAY_FORMAT.getKey(),
    PayConstant.ALIPAY_CHARSET.getKey(),
    alipayConfig.getAliPublicKey(),
    PayConstant.ALIPAY_SIGN_TYPE_RSA2.getKey());
  return alipayClient;
 }

 //獲取商傢支付寶的配置信息
 public AlipayConfig getConfigByAppCode(String appCode) {
  AlipayConfig alipayConfig = alipayConfigService.selectByAppCode(appCode);
  return alipayConfig;
 }


 /**
  * 支付寶退款接口
  * @param aliPayRefundParam
  * @return
  */
 public ReturnMsg aliPayRefund(AliPayRefundParam aliPayRefundParam){
  ReturnMsg returnMsg=new ReturnMsg();

  String appCode=aliPayRefundParam.getAppCode();
  AlipayClient alipayClient = getAlipayClientByAppCode(appCode);

  AlipayTradeRefundResponse response = null;
  AlipayTradeRefundModel model = new AlipayTradeRefundModel();
  //訂單支付時傳入的商戶訂單號,不能和 trade_no同時為空。
  model.setOutTradeNo(aliPayRefundParam.getOutTradeNo());
  //支付寶交易號,和商戶訂單號不能同時為空
  //model.setTradeNo(aliPayRefundParam.getTradeNo());
  //標識一次退款請求,同一筆交易多次退款需要保證唯一,如需部分退款,則此參數必傳。
  model.setOutRequestNo(aliPayRefundParam.getOutRequestNo());
  //	需要退款的金額,該金額不能大於訂單金額,單位為元,支持兩位小數
  model.setRefundAmount(aliPayRefundParam.getRefundAmount());
  //退款的原因說明
  model.setRefundReason(aliPayRefundParam.getRefundReason());

  /**
   * 創建支付寶掃碼支付請求接口類,設置相關請求處理信息,準備請求下單
   */
  AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
  request.setBizModel(model);
  //商戶外網可以訪問的異步地址,不寫就是不回調
  request.setNotifyUrl(notifyUrl + PayConstant.ALIPAY_05.getKey() + "/" + aliPayRefundParam.getAppCode() + "/" + aliPayRefundParam.getDh());
  //支付成功返回地址
  request.setReturnUrl(aliPayRefundParam.getRedirectUrl());

  // 通過api的方法請求阿裡接口獲得反饋 alipayClient.pageExecute(request)
  try {
   logger.info("支付寶退款請求完整報文:{}",JSON.toJSONString(request));
   response = alipayClient.execute(request)/**/;
  } catch (AlipayApiException e) {
   logger.info("支付寶退款失敗,\n本次下單的訂單號:{},\n相關報錯信息為:{}", aliPayRefundParam.getDh(), response, e);
   throw new BaseException(QYError.msg("調用支付寶預退款失敗![" + e.getMessage() + "]"));
  }catch (Exception e){
   e.printStackTrace();
   throw new BaseException(QYError.msg("支付寶預退款失敗![" + e.getMessage() + "]"));
  }

  //打印返回信息
  logger.info("支付寶退款失敗:{}", JSON.toJSONString(response));
  //判斷預下單返回狀態
  if (response.isSuccess()&&"Y".equals(response.getFundChange())) {
   logger.info("AliPayServiceImpl.aliScanPay----->\n支付寶退款成功,\n本次下單的訂單號:{},商務訂單號為,{}", aliPayRefundParam.getDh(), aliPayRefundParam.getOutTradeNo());
   return returnMsg.setData("退款成功");

  } else {
   logger.error("AliPayServiceImpl.aliScanPay----->\n調用支付寶退款接口失敗!\n具體信息:\n{}", response.getBody());
   throw new BaseException(QYError.msg("調用支付寶退款接口失敗![" + response.getBody() + "]"));
  }
 }

}

4、WxPayService

package com.qcsoft.payment.service;

import com.qcsoft.commonbean.bean.payment.WxMinConfig;
import com.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
import com.qcsoft.commonbean.bean.payment.wx.bean.WxRefund;
import com.qcsoft.commonbean.bean.payment.wx.bean.entpay.EntPayParam;
import com.qcsoft.commonbean.bean.payment.wx.bean.entpay.EntPayResult;
import com.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayUnifiedOrderRequest;
import com.qcsoft.commonbean.bean.payment.wx.bean.result.BaseWxPayResult;
import com.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayOrderQueryResult;
import com.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayUnifiedOrderResult;
import com.qcsoft.commonbean.bean.payment.wx.config.WxPayConfig;
import com.qcsoft.commonbean.bean.payment.wx.exception.WxPayException;


/**
 * 微信預支付
 * @param appId 應用ID(微信公眾號)
 * @param mchId 商務號ID
 * @param mchKey 商務號密鑰
 * @param notifyUrl 異步通知地址
 * @param signType 簽名類型
 * @param body 描述
 * @param totalFee 金額
 * @param spbillCreateIp app和h5支付需要用戶的真實請求地址
 * @param tradeType
 * @param outTradeNo
 * @return
 */
public interface WxPayService {
 /**
  *
  * @param config {appId:應用ID,mchId:商務號ID,mchKey:商務號密鑰,notifyUrl:異步通知地址,signType:簽名類型}
  * @param request {body:訂單描述,totalFee:金額,
  *    spbillCreateIp:app和h5支付需要用戶的真實請求地址Native支付填調用微信支付API的機器IP,
  *    tradeType:SAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付,統一下單接口trade_type的傳參可參考這裡,
  *    outTradeNo:商戶訂單號,productId:商品Id(掃碼支付必傳,其他選填),openid:公眾號openId}
  * @return
  */
 WxPayUnifiedOrderResult wxPrePay(WxPayConfig config, WxPayUnifiedOrderRequest request);

 /**
  * 根據appCode獲取商傢微信支付配置
  * @param appCode
  * @return
  */
 WxPayConfig getWxPayConfigByAppCode(String appCode,String bmCode);

 WxPayConfig getWxMinPayConfigByAppCode(String appCode,String sysSoftwareCode);

 /**
  * 封裝預下單參數實體
  * @param orderParam 預支付接口參數實體
  * @param order 點單
  * @return
  */
 WxPayUnifiedOrderRequest packRequestParam(PreOrderParam orderParam);


 /**
  * 查詢訂單
  * @param appCode 商傢編碼
  * @param dh 訂單號
  * @param sysSoftwareCode
  */
 WxPayOrderQueryResult wxPayOrderQuery(String appCode, String bmCode, String dh, Integer type, String sysSoftwareCode);


 /**
  * 企業支付
  * @param params
  * @return:
  * @Author: 
  * @date: 
  */
 BaseWxPayResult entPay(EntPayParam params) throws WxPayException;
}

WxPayServiceImpl

package com.qcsoft.payment.service.impl;

import com.alibaba.fastjson.JSON;
import com.qcsoft.commonbean.bean.payment.PayLog;
import com.qcsoft.commonbean.bean.payment.WxConfig;
import com.qcsoft.commonbean.bean.payment.WxMinConfig;
import com.qcsoft.commonbean.bean.payment.common.PayConstant;
import com.qcsoft.commonbean.bean.payment.common.PayNotify;
import com.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
import com.qcsoft.commonbean.bean.payment.wx.bean.entpay.*;
import com.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayOrderQueryRequest;
import com.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayUnifiedOrderRequest;
import com.qcsoft.commonbean.bean.payment.wx.bean.result.BaseWxPayResult;
import com.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayOrderQueryResult;
import com.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayUnifiedOrderResult;
import com.qcsoft.commonbean.bean.payment.wx.config.WxPayConfig;
import com.qcsoft.commonbean.bean.payment.wx.exception.WxPayException;
import com.qcsoft.commonbean.bean.payment.wx.handler.EntPayHandler;
import com.qcsoft.commonbean.bean.payment.wx.handler.WxPayHandler;
import com.qcsoft.commonbean.bean.payment.wx.handler.impl.EntPayHandlerImpl;
import com.qcsoft.commonbean.bean.payment.wx.handler.impl.WxPayHandlerApacheHttpImpl;
import com.qcsoft.payment.commns.exception.BaseException;
import com.qcsoft.payment.commns.exception.QYError;
import com.qcsoft.payment.commns.utils.DateUtils;
import com.qcsoft.payment.commns.utils.RedisUtil;
import com.qcsoft.payment.service.PayLogService;
import com.qcsoft.payment.service.WxConfigService;
import com.qcsoft.payment.service.WxMinConfigService;
import com.qcsoft.payment.service.WxPayService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;

@Service
@Slf4j
public class WxPayServiceImpl implements WxPayService {
 private static final Logger logger = LoggerFactory.getLogger(WxPayServiceImpl.class);

 @Value("${payNotifyUrl}")
 private String notifyUrl;
 @Autowired
 private RedisUtil redisUtil;
 @Autowired
 private WxConfigService wxConfigService;
 @Autowired
 private WxMinConfigService wxMinConfigService;
 @Autowired
 private PayLogService payLogService;

 /**
  * @param config {appId:應用ID,mchId:商務號ID,mchKey:商務號密鑰,notifyUrl:異步通知地址,signType:簽名類型}
  * @param request {body:訂單描述,totalFee:金額,
  *    spbillCreateIp:app和h5支付需要用戶的真實請求地址Native支付填調用微信支付API的機器IP,
  *    tradeType:SAPI--公眾號支付、NATIVE--原生掃碼支付、APP--app支付,統一下單接口trade_type的傳參可參考這裡,
  *    outTradeNo:商戶訂單號,productId:商品Id(掃碼支付必傳,其他選填),openid:公眾號openId} 還有很多參數選填
  * @return
  * @throws WxPayException
  */
 @Override
 public WxPayUnifiedOrderResult wxPrePay(WxPayConfig config, WxPayUnifiedOrderRequest request) {
  logger.info("WxPayServiceImpl.wxPrePay--->>\n微信預支付,\n商務訂單號:[{}]", request.getOutTradeNo());
  WxPayHandler wx = new WxPayHandlerApacheHttpImpl();
  WxPayUnifiedOrderResult orderResult = null;
  wx.setConfig(config);
  log.info("WxPayUnifiedOrderResult ={}", config.getNotifyUrl());
  try {
   orderResult = wx.unifiedOrder(request);
  } catch (WxPayException e) {
   logger.error("WxPayServiceImpl.wxPrePay--->>\n微信預支付失敗,\n商務訂單號:[{}]", request.getOutTradeNo(), orderResult);
   logger.error("異常信息{}", e.getMessage());
   throw new BaseException(QYError.msg("訂單號[" + request.getOutTradeNo() + "]預支付失敗!"));
  }
  return orderResult;
 }


 /**
  * 根據商傢編碼獲取微信商戶配置信息
  *
  * @param appCode
  * @return
  */
 @Override
 public WxPayConfig getWxPayConfigByAppCode(String appCode, String bmCode) {
  logger.info("WxPayServiceImpl.getWxPayConfigByAppCode--->>\n獲取微信支付配置信息:appCode[{}],bmCode[{}]", appCode, bmCode);
  WxConfig config = null;
  WxPayConfig wxPayConfig = new WxPayConfig();
  /**
   * 獲取商傢支付寶配置信息(優先級:1-redis,2-mysql,3-用戶系統)
   */
  try {
   //2、mysql
   if (config == null) {
    if (StringUtils.isNotBlank(bmCode)) {
     config = wxConfigService.selectByBmCode(bmCode, appCode);
     //如果部門取不到,則去商傢的配置
     if (config == null)
      config = wxConfigService.selectByAppCode(appCode);
    } else {
     config = wxConfigService.selectByAppCode(appCode);
    }
   }
   if (config == null) {
    logger.warn("WxPayServiceImpl.getWxPayConfigByAppCode--->>\n獲取微信支付配置信息失敗:[{}]", appCode);
    throw new BaseException(QYError.msg("獲取微信支付配置信息失敗!"));
   }
  } catch (Exception e) {
   logger.error("WxPayServiceImpl.getWxPayConfigByAppCode--->>\n獲取微信支付配置信息失敗:[{}]", e);
   throw new BaseException(QYError.msg("獲取微信支付配置信息失敗!"));
  }
  //根據appCode查詢商傢微信配置信息
  wxPayConfig.setAppId(config.getAppid());
  wxPayConfig.setMchId(config.getMchId());
  wxPayConfig.setMchKey(config.getMchKeySecret());
  wxPayConfig.setSignType(PayConstant.WXPAY_SIGNTYPE_MD5.getKey());
  wxPayConfig.setKeyUrl(config.getCrtPath());
  wxPayConfig.setKeyPath(config.getCrtPath());
  log.info("獲取微信公眾號配置為 [{}],轉為微信支付實體為 [{}]",config,wxPayConfig);
  return wxPayConfig;
 }


 @Override
 public WxPayConfig getWxMinPayConfigByAppCode(String appCode, String sysSoftwareCode) {
  logger.error("WxPayServiceImpl.getWxMinPayConfigByAppCode--->>\n獲取微信小程序支付配置信息:[{}]", appCode);
  if (StringUtils.isBlank(sysSoftwareCode)) {
   sysSoftwareCode = "store-service";
  }
  WxMinConfig config = null;
  WxPayConfig wxPayConfig = new WxPayConfig();
  /**
   * 獲取商傢支付寶配置信息(優先級:1-redis,2-mysql,3-用戶系統)
   */
  try {
   if (config == null) {
    //config = wxMinConfigService.selectByAppCode(appCode);
    config = wxMinConfigService.selectBySysSoftwareCode(appCode,sysSoftwareCode);
   }
   if (config == null) {
    logger.warn("WxPayServiceImpl.getWxMinPayConfigByAppCode--->>\n獲取微信小程序支付配置信息失敗:[{}]", appCode);
    throw new BaseException(QYError.msg("獲取微信支付配置信息失敗!"));
   }
  } catch (Exception e) {
   logger.error("WxPayServiceImpl.getWxMinPayConfigByAppCode--->>\n獲取微信小程序支付配置信息失敗:[{}]", e);
   throw new BaseException(QYError.msg("獲取微信小程序支付配置信息失敗!"));
  }
  //根據appCode查詢商傢微信配置信息
  wxPayConfig.setAppId(config.getAppid());
  wxPayConfig.setMchId(config.getMchId());
  wxPayConfig.setMchKey(config.getMchKeySecret());
  wxPayConfig.setSignType(PayConstant.WXPAY_SIGNTYPE_MD5.getKey());
  wxPayConfig.setKeyUrl(config.getCrtPath());
  wxPayConfig.setKeyPath(config.getCrtPath());
  log.info("獲取微信小程序退款配置為 [{}],轉為微信支付實體為 [{}]",config,wxPayConfig);
  return wxPayConfig;
 }

 /**
  * 封裝預下單參數實體
  *
  * @param orderParam 預支付接口參數實體
  * @param order  點單
  * @return
  */
 @Override
 public WxPayUnifiedOrderRequest packRequestParam(PreOrderParam orderParam) {
  Date date = new Date();
  BigDecimal paramAmount = new BigDecimal(orderParam.getTotalAmount().toString());
  BigDecimal multiplyNum = new BigDecimal("100");
  WxPayUnifiedOrderRequest request = WxPayUnifiedOrderRequest.newBuilder()
    .body(orderParam.getBody())
    .totalFee(paramAmount.multiply(multiplyNum).intValue())
    .spbillCreateIp(orderParam.getReqId())
    .notifyUrl(notifyUrl + PayConstant.WXPAY_09.getKey())
    .tradeType(orderParam.getTradeType())
    .outTradeNo(orderParam.getOutTradeNo())
    .build();
  log.info("WxPayUnifiedOrderRequest = {}", PayConstant.WXPAY_09.getKey());

  request.setProductId(orderParam.getDh());
  request.setDetail(orderParam.getSubject());
  PayNotify payNotify = new PayNotify();
  payNotify.setAppCode(orderParam.getAppCode());
  payNotify.setCode(orderParam.getBmCode());
  payNotify.setDh(orderParam.getDh());
  request.setAttach(JSON.toJSONString(payNotify));
  if (orderParam.getTradeType().equals(PayConstant.JSAPI.toString())) {
   request.setOpenid(orderParam.getOpenId());
  }
  //開始時間
  request.setTimeStart(DateUtils.getLastMinute(date, 0));
  //有效期
  request.setTimeExpire(orderParam.getTimeExpire());
  return request;
 }

 /**
  * 訂單查詢
  *
  * @param appCode 商傢編碼
  * @param dh  訂單號
  * @param sysSoftwareCode
  * @return
  */
 @Override
 public WxPayOrderQueryResult wxPayOrderQuery(String appCode, String bmCode, String dh, Integer type, String sysSoftwareCode) {
  logger.info("WxPayServiceImpl.wxPayOrderQuery--->>\n微信訂單查詢,\n本次查詢的商傢編碼為:[{}],商務訂單號:[{}]", appCode, dh);
  WxPayHandler handler = new WxPayHandlerApacheHttpImpl();
  WxPayOrderQueryRequest request = new WxPayOrderQueryRequest();
  WxPayOrderQueryResult queryResult = null;
  WxPayConfig config = null;


  try {
   PayLog payLog = payLogService.selectByDh(dh);
   if (payLog==null) {
    //商傢的微信支付
    if (type == null || type == 1) {
     bmCode = null;
     config = this.getWxPayConfigByAppCode(appCode, bmCode);
     //部門的微信支付支付
    } else if (type == 2) {
     config = this.getWxPayConfigByAppCode(appCode, bmCode);
     //商傢小程序支付
    } else if (type == 3) {
     config = this.getWxMinPayConfigByAppCode(appCode,sysSoftwareCode);
    }
   }else{
    config = JSON.parseObject(payLog.getPayConfigJsonStr(), WxPayConfig.class);
   }
   request.setOutTradeNo(dh);
   handler.setConfig(config);
   queryResult = handler.queryOrder(request);
   logger.info("WxPayServiceImpl.wxPayOrderQuery--->>\n微信訂單查詢成功,\n返回包信息:[{}]", JSON.toJSONString(queryResult));
  } catch (WxPayException e) {
   logger.error("WxPayServiceImpl.wxPayOrderQuery--->>\n微信訂單查詢失敗,\n商務訂單號:[{}]", dh);
   throw new BaseException(QYError.msg("微信訂單查詢失敗,商務訂單號:[{}]" + dh + ""));
  }
  return queryResult;
 }
 /**
  * 企業支付
  * @param params
  * @return: com.qcsoft.commonbean.bean.payment.wx.bean.result.BaseWxPayResult
  * @Author: 
  * @date:
  */
 @Override
 public BaseWxPayResult entPay(EntPayParam params) throws WxPayException {
  WxPayHandler wxPayHandler = new WxPayHandlerApacheHttpImpl();
  WxPayConfig config = null;
  EntPayResult result = null;
  EntPayBankResult bankResult = null;
  if (params.getTradeType() != null && params.getTradeType() == 3) {
   config = this.getWxMinPayConfigByAppCode(params.getAppCode(),params.getSysSoftwareCode());
  } else {
   config = this.getWxPayConfigByAppCode(params.getAppCode(), params.getBmCode());
  }
  config.setUseKey(true);
  wxPayHandler.setConfig(config);
  if (params.getTradeType()==1) {
   EntPayRequest request = packEntPayRequest(params,config);
   EntPayHandler entPayHandler = new EntPayHandlerImpl(wxPayHandler);

   result = entPayHandler.entPay(request);
   return result;
  }else{
   EntPayBankRequest request = packEntPayBankRequest(params);
   EntPayHandler entPayHandler = new EntPayHandlerImpl(wxPayHandler);
   bankResult = entPayHandler.payBank(request);
   return bankResult;
  }
 }
 /**
  * 封裝微信企業支付請求參數
  * @param params
  * @return: com.qcsoft.commonbean.bean.payment.wx.bean.entpay.EntPayRequest
  * @Author: 
  * @date: 
  */
 public EntPayRequest packEntPayRequest(EntPayParam params,WxPayConfig config) {
  EntPayRequest request = new EntPayRequest();
  request.setAmount(params.getAmount().multiply(new BigDecimal("10")).intValue());
  request.setCheckName("NO_CHECK");
  request.setOpenid(params.getOpenid());
  request.setSpbillCreateIp(params.getSpbillCreateIp());
  request.setPartnerTradeNo(params.getPartnerTradeNo());
  request.setMchAppid(config.getAppId());
  request.setMchId(config.getMchId());
  request.setDescription(params.getDesc());
  return request;
 }


 /**
  * 封裝銀行卡企業支付參數
  * @param params
  * @return: com.qcsoft.commonbean.bean.payment.wx.bean.entpay.EntPayBankRequest
  * @Author: 
  * @date: 
  */
 public EntPayBankRequest packEntPayBankRequest(EntPayParam params) {
  EntPayBankRequest request = new EntPayBankRequest();
  request.setAmount(params.getAmount().multiply(new BigDecimal("10")).intValue());
  request.setBankCode(params.getBankCode());
  request.setEncTrueName(params.getEncTrueName());
  request.setPartnerTradeNo(params.getPartnerTradeNo());
  request.setDescription(params.getDesc());
  return request;
 }
}

5、這些類是和數據庫交互的增刪查該類

 @Autowired
 private WxConfigService wxConfigService;
 @Autowired
 private WxMinConfigService wxMinConfigService;
 @Autowired
 private PayLogService payLogService;
 @Autowired
 private AlipayConfigService alipayConfigService;
 ```

到此這篇關於Java 實現微信和支付寶支付功能的文章就介紹到這瞭,更多相關Java 微信和支付寶支付內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: