一、前期准备

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);@Autowiredprivate 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());@Autowiredprivate AliPayService aliPayService;@Autowiredprivate WxPayService wxPayService;@Autowiredprivate ChinaumsPayService chinaumsPayService;@Autowiredprivate UserUtil userUtil;@Autowiredprivate PayLogService payLogService;@Overridepublic 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()); // appidpaypackageParams.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);@Autowiredprivate AlipayConfigService alipayConfigService;@Autowiredprivate RedisUtil redisUtil;@Value("${payNotifyUrl}")private String notifyUrl;/*** APP支付* 参数加签*/@Overridepublic 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();}/*** 扫码支付* 参数加签*/@Overridepublic 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支付* 参数加签*/@Overridepublic 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*/@Overridepublic 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() + "]"));}}@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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;@Autowiredprivate RedisUtil redisUtil;@Autowiredprivate WxConfigService wxConfigService;@Autowiredprivate WxMinConfigService wxMinConfigService;@Autowiredprivate 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*/@Overridepublic 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*/@Overridepublic 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、mysqlif (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;}@Overridepublic 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*/@Overridepublic 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*/@Overridepublic 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:*/@Overridepublic 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、这些类是和数据库交互的增删查该类

 @Autowiredprivate WxConfigService wxConfigService;@Autowiredprivate WxMinConfigService wxMinConfigService;@Autowiredprivate PayLogService payLogService;@Autowiredprivate AlipayConfigService alipayConfigService;

总结

篇幅有限!篇幅有限!关于JAVA实现支付宝微信支付功能的文章,就聊到这儿啦…啦…啦…
以上小编所介绍的全部相关的笔记资料都已整理成册,不论是Redis面试+Redis实战pdf,还是MongDB快速上手+MongDB集群安全等手写pdf笔记,想白嫖都很so easy!!
——如果你get到了,那就点个赞转发支持一波吧!
——整理不易,白嫖私信,100%回复分享!
——也可以微信小助手哦:xcw18874131605
——祝前程似锦,offer不断,好好学习,天天向上!

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持,需要更多资料的同学可以评论私信我,记得一键三连哦谢谢大家

哈哈!没想到吧!Java也可以 实现微信和支付宝支付功能(附代码)相关推荐

  1. 微信扫码支付功能详细教程————Java

    前言  首先声明 我并非原创 原创是 http://blog.csdn.net/wangqiuyun/article/details/51241064 我只是在前辈的基础 加以解释说明 还有自己的一些 ...

  2. java中ssm付款代码,ssm实现支付宝支付功能(图文详解)

    目录 1.支付宝沙箱环境测试 2.支付宝整合到ssm环境 3.微信支付整合到ssm环境 一.支付宝测试环境代码测试 1.下载电脑网站的官方demo: 2.下载解压导入eclipse readme.tx ...

  3. java web电脑网站微信扫码支付(Servlet+JSP)

    上篇文章写到了app开发中的微信支付和支付宝支付连接:https://blog.csdn.net/qq_35318713/article/details/92832397, 这次再把电脑网站扫码支付的 ...

  4. java实现微信小程序支付功能

    微信支付-开发者文档: https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_5_1.shtml 生成订单 /*** 生成订单*/@User@A ...

  5. Java 实现微信和支付宝支付

    一.前期准备 1.申请好微信商户号appid,拿到商户id和商户秘钥,退款的话需要商户证书 2.申请好支付宝商户号appid,商户公钥和秘钥(需要用支付宝工具自己生成),支付宝退款不需要证书 二.数据 ...

  6. 我也没想到,Java开发 API接口可以不用写 Controller了

    大家好,我是小富~ 今天介绍我正在用的一款高效敏捷开发工具magic-api,顺便分享一点工作中使用它的心得 缘起 先说一下我为什么会使用这个工具? 最近新启动一个项目,业务并不算复杂,那种典型的管理 ...

  7. java 中调用支付宝支付功能的接口

    支付宝接口: 申请支付宝接口服务:  1.https://fuwu.alipay.com/platform/doc.htm#c11    Java-JDK 1.5 SDK 2.https://csha ...

  8. Java后台实现网站微信扫码登录功能,获取用户openid,及微信用户信息(小程序码方案),关联微信小程序(个人主体小程序也可以)

    目录 前言 操作流程 1.注册微信小程序 2.通过后台获取小程序码 注意事项 时序图理解 方案实现步骤 前言 很多业务场景之下我们需要实现微信扫码登录检测登录状态的需求,或需要同步网站与小程序的用户信 ...

  9. 不愧是京东大牛!用Java实现黄金分割数的示例详解(附代码)

    这篇文章主要介绍了java 实现黄金分割数的示例详解,具有很好的参考价值,希望对大家有所帮助.一起跟随小编过来看看吧. 黄金分割数 0.618 与美学有重要的关系.舞台上报幕员所站的位置大约就是舞台宽 ...

最新文章

  1. 对于U盘做系统,win8降级到win7系统的心得体会
  2. 黑客用python还是ruby-请问为什么我选择了Ruby而不是Python?
  3. CSS 关于雪碧图预处理和后处理方案的讨论
  4. 从普通JAVA程序员到阿里P8架构师,他用了六年
  5. for of 和 for in 在数组和对象中的区别
  6. 浙江省计算机二级c理论题库,浙江省计算机级考试二级《C程序设计》上机考试题库.doc...
  7. 星痕 轻松实现大屏数据可视化_数据美的历程有多难?大屏可视化轻松帮你实现...
  8. 【C++】对象作为函数参数【原创技术】
  9. spring @Transactional注解的使用和失效场景
  10. extern dllInport用法
  11. 341.扁平化嵌套列表迭代器
  12. 【数字电子技术课程设计】多功能数字电子钟的设计
  13. Spring Boot菜鸟示例——Hello World
  14. 书籍新增类别下拉框上下架
  15. 软考信息系统项目管理师论文范文:论项目的质量管理论项目的质量管理
  16. 光环PMP一模知识点解析
  17. vue 读取shapefile文件转成GeoJson
  18. go技术文章梳理(2017)
  19. python删除数据集中的空值_关于在python中如何使用pandas库读取excel表格后 删除含有空值的列...
  20. [译] 强化学习中的好奇心与拖延症

热门文章

  1. 开方在java中怎么计算_不使用java JDK已有的API实现任意数字的开方
  2. 跳槽加薪利器:2019需求最旺盛的十大IT技能
  3. SIM A7670C MQTT
  4. C++11 左值、右值、右值引用详解
  5. Stable Diffusion使用“面部修复”时报TypeError: ‘NoneType‘ object is not subscriptable错
  6. 4项目管理--项目整合管理
  7. 在线画html表格,网页表格的各种画法(Html代码)
  8. 【尚硅谷前端html+css】02_css
  9. De Morgan's laws
  10. 基于PCNN脉冲耦合神经网络的图像分割