Java 实现微信和支付宝支付功能
一、前期准备
1、申请好微信商户号appid,拿到商户id和商户秘钥,退款的话需要商户证书
2、申请好支付宝商户号appid,商户公钥和秘钥(需要用支付宝工具自己生成),支付宝退款不需要证书
二、数据库表设计
1、微信支付配置表
CREATETABLE`py_wx_config`( `wx_config_id`varchar(18)NOTNULLCOMMENT'微信支付配置ID', `appid`varchar(128)DEFAULTNULLCOMMENT'微信公众号ID', `mch_id`varchar(128)DEFAULTNULLCOMMENT'商户号ID', `mch_key_secret`varchar(2200)DEFAULTNULLCOMMENT'商户安全密钥', `crt_path`varchar(200)DEFAULTNULLCOMMENT'商户证书存放路径', `app_secret`varchar(2200)DEFAULTNULLCOMMENT'公众号安全密钥', `create_id`varchar(18)DEFAULTNULLCOMMENT'创建人', `create_time`datetimeDEFAULTNULLCOMMENT'创建时间', `upd_id`varchar(18)DEFAULTNULLCOMMENT'修改人', `upd_time`datetimeDEFAULTNULLCOMMENT'修改时间', `delete_flag`tinyint(1)NOTNULLDEFAULT'0'COMMENT'删除标志', `app_code`varchar(18)NOTNULLCOMMENT'商家编码', `bm_code`varchar(20)DEFAULTNULLCOMMENT'部门编码', PRIMARYKEY(`wx_config_id`)USINGBTREE )ENGINE=InnoDBDEFAULTCHARSET=utf8mb4ROW_FORMAT=COMPACTCOMMENT='微信支付配置';
2、微信小程序支付配置表
CREATETABLE`py_wx_min_config`( `wx_min_config_id`varchar(18)NOTNULLCOMMENT'微信支付配置ID', `appid`varchar(128)DEFAULTNULLCOMMENT'微信公众号ID', `mch_id`varchar(128)DEFAULTNULLCOMMENT'商户号ID', `mch_key_secret`varchar(2200)DEFAULTNULLCOMMENT'商户安全密钥', `crt_path`varchar(200)DEFAULTNULLCOMMENT'商户证书存放路径', `app_secret`varchar(2200)DEFAULTNULLCOMMENT'公众号安全密钥', `create_id`varchar(18)DEFAULTNULLCOMMENT'创建人', `create_time`datetimeDEFAULTNULLCOMMENT'创建时间', `upd_id`varchar(18)DEFAULTNULLCOMMENT'修改人', `upd_time`datetimeDEFAULTNULLCOMMENT'修改时间', `delete_flag`tinyint(1)NOTNULLDEFAULT'0'COMMENT'删除标志', `app_code`varchar(18)NOTNULLCOMMENT'商家编码', `sys_software_code`varchar(18)DEFAULTNULLCOMMENT'系统编码', PRIMARYKEY(`wx_min_config_id`)USINGBTREE )ENGINE=InnoDBDEFAULTCHARSET=utf8mb4ROW_FORMAT=COMPACTCOMMENT='微信支付配置';
3、支付宝支付配置表
CREATETABLE`py_alipay_config`( `alipay_config_id`varchar(18)NOTNULLCOMMENT'支付宝支付配置ID', `ali_private_key`varchar(2200)DEFAULTNULLCOMMENT'支付宝密钥', `ali_public_key`varchar(2200)DEFAULTNULLCOMMENT'支付宝公钥', `ali_appid`varchar(128)DEFAULTNULLCOMMENT'支付宝appid', `create_id`varchar(18)DEFAULTNULLCOMMENT'创建人', `create_time`datetimeDEFAULTNULLCOMMENT'创建时间', `upd_id`varchar(18)DEFAULTNULLCOMMENT'修改人', `upd_time`datetimeDEFAULTNULLCOMMENT'修改时间', `delete_flag`tinyint(1)NOTNULLDEFAULT'0'COMMENT'删除标志', `app_code`varchar(18)NOTNULLCOMMENT'商家编码', PRIMARYKEY(`alipay_config_id`)USINGBTREE )ENGINE=InnoDBDEFAULTCHARSET=utf8mb4ROW_FORMAT=COMPACTCOMMENT='支付宝支付配置';
4、支付流水记录表
CREATETABLE`py_pay_log`( `pay_log_id`varchar(18)NOTNULLCOMMENT'支付流水ID', `pay_no`varchar(20)DEFAULTNULLCOMMENT'支付订单号', `third_id`varchar(64)DEFAULTNULLCOMMENT'微信支付宝订单ID', `money_type`varchar(20)DEFAULTNULLCOMMENT'支付类型0-微信1-支付宝2-会员卡3-银联', `mq_topic`varchar(100)DEFAULTNULLCOMMENT'MQ主题', `mq_status`tinyint(3)DEFAULTNULLCOMMENT'MQ发送状态0-待发送1-已发送2-发送失败', `mq_remark`varchar(100)DEFAULTNULLCOMMENT'MQ发送备注', `request`textCOMMENT'发送数据', `response`textCOMMENT'返回数据', `fee`decimal(14,2)DEFAULTNULLCOMMENT'订单金额', `create_id`varchar(18)DEFAULTNULLCOMMENT'创建人', `create_time`datetimeDEFAULTNULLCOMMENT'创建时间', `upd_id`varchar(18)DEFAULTNULLCOMMENT'修改人', `upd_time`datetimeDEFAULTNULLCOMMENT'修改时间', `delete_flag`tinyint(1)NOTNULLDEFAULT'0'COMMENT'删除标志', `app_code`varchar(18)NOTNULLCOMMENT'商家编码', `pay_config_json_str`longtextCOMMENT'支付配置', PRIMARYKEY(`pay_log_id`)USINGBTREE )ENGINE=MyISAMDEFAULTCHARSET=utf8mb4ROW_FORMAT=DYNAMICCOMMENT='支付流水';
5、支付失败记录表
CREATETABLE`pay_fail_log`( `pay_id`varchar(18)NOTNULL, `json_date`varchar(500)DEFAULTNULL, `create_id`varchar(18)DEFAULTNULL, `create_time`datetimeDEFAULTNULL, `update_id`varchar(18)DEFAULTNULL, `update_time`datetimeDEFAULTNULL, `app_code`varchar(18)NOTNULL, `delete_flag`tinyint(1)DEFAULT'0'COMMENT'是否删除:0-否;1-是', PRIMARYKEY(`pay_id`)USINGBTREE )ENGINE=InnoDBDEFAULTCHARSET=utf8mb4ROW_FORMAT=COMPACT;
三、依赖引入
org.springframework.boot spring-boot-starter-parent 2.1.3.RELEASE 4.0.0 com.pay qc-payment 2.3 qc-payment http://www.example.com UTF-8 1.7 1.7 Greenwich.SR1 org.springframework.boot spring-boot-starter-data-redis org.springframework.boot spring-boot-starter-web org.springframework.cloud spring-cloud-starter-netflix-eureka-client org.springframework.cloud spring-cloud-starter-netflix-zuul com.alipay.sdk alipay-sdk-java 3.3.4.ALL org.springframework.boot spring-boot-starter-test test org.springframework.retry spring-retry org.springframework.cloud spring-cloud-starter-netflix-hystrix com.auth0 java-jwt 3.4.1 org.apache.commons commons-lang3 3.3.2 com.alibaba druid 1.1.12 org.mybatis.spring.boot mybatis-spring-boot-starter 2.0.0 mysql mysql-connector-java javax.persistence persistence-api 1.0.2 tk.mybatis mapper 4.0.3 org.projectlombok lombok provided commons-io commons-io 2.4 com.pay easyqinyu-tools 0.0.1-SNAPSHOT com.github.pagehelper pagehelper 5.1.2 com.github.pagehelper pagehelper-spring-boot-autoconfigure 1.2.3 com.github.pagehelper pagehelper-spring-boot-starter 1.2.3 com.qcsoft qc-swagger-ui 0.0.1-SNAPSHOT compile com.google.zxing core 3.3.0 com.alibaba fastjson RELEASE compile org.apache.httpcomponents httpclient ${httpclient.version} com.google.code.gson gson 2.8.2 com.aliyun aliyun-java-sdk-core 3.3.1 com.github.1991wangliang aliyun-java-sdk-dysmsapi 1.0.0 org.springframework.kafka spring-kafka com.thoughtworks.xstream xstream 1.4.10 org.dom4j dom4j 2.1.1 com.github.binarywang weixin-java-common 3.3.4.B org.jodd jodd-http compile org.apache.commons commons-lang3 commons-beanutils commons-beanutils 1.9.3 jdom jdom 1.0 org.bouncycastle bcpkix-jdk15on 1.59 org.jodd jodd-http 3.7.1 com.google.zxing core 3.2.1 com.qcsoft qc-commonbean 0.0.1-SNAPSHOT org.springframework.cloud spring-cloud-starter-openfeign com.xuxueli xxl-job-core 2.0.1 org.springframework.cloud spring-cloud-starter-netflix-hystrix-dashboard org.springframework.boot spring-boot-starter-actuator org.springframework.cloud spring-cloud-dependencies ${spring-cloud.version} pom import qc-payment org.springframework.boot spring-boot-maven-plugin org.apache.maven.plugins maven-compiler-plugin 8 8
四、程序实现
1、Controller
packagecom.qcsoft.payment.controller;
importcom.alibaba.fastjson.JSON;
importcom.qcsoft.commonbean.bean.common.SwaggerConstant;
importcom.qcsoft.commonbean.bean.payment.common.PrePayResult;
importcom.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
importcom.qcsoft.commonbean.bean.payment.wx.exception.WxPayException;
importcom.qcsoft.commonbean.bean.payment.wx.util.QrcodeUtils;
importcom.qcsoft.easyqinyutools.message.ReturnMsg;
importcom.qcsoft.payment.controller.commom.BaseController;
importcom.qcsoft.payment.service.PayService;
importcom.qcsoft.swaggerui.anno.ApiTag;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.web.bind.annotation.*;
importjavax.imageio.ImageIO;
importjavax.servlet.http.HttpServletRequest;
importjavax.servlet.http.HttpServletResponse;
importjava.awt.image.BufferedImage;
importjava.io.IOException;
/**
*@Description:支付控制中心
*@Author:
*@Date:
*/
@RestController
@RequestMapping("/v2")
publicclassPayControllerextendsBaseController{
privatestaticfinalLoggerlogger=LoggerFactory.getLogger(PayController.class);
@Autowired
privatePayServicepayService;
//privatefinalAtomicIntegertick=newAtomicInteger();
/**
*统一预支付接口(统一下单)
*
*@paramorderParam{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:中途退出}
*@paramtokentoken
*@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支付参数支付串
*}
*@throwsWxPayException
*/
@RequestMapping(value="/prePayOrder")
@ApiTag(SwaggerConstant.PAYMENT_001)
publicReturnMsgprePayOrder(@RequestBodyPreOrderParamorderParam){
Stringmetadata=JSON.toJSONString(orderParam);
logger.info("PayController.prePayOrder----\n正在请求支付....,参数为>>>>{}",metadata);
ReturnMsgret=newReturnMsg();
//预下单
PrePayResultprePayResult=this.payService.payPreOrder(orderParam);
ret.setData(prePayResult);
returnret.success("下单成功,订单有效期为"+orderParam.getTimeExpire());
}
/**
*生成支付二维码
*
*@paramurl二维码地址
*@throwsIOException
*/
@RequestMapping(value="/createQrCode/url")
@ApiTag(SwaggerConstant.PAYMENT_001)
publicvoidcreateQrCode(@PathVariableStringurl,HttpServletRequestrequest,HttpServletResponseresponse)throwsIOException{
StringqueryString=request.getQueryString();
BufferedImagebufferedImage=QrcodeUtils.encode(url+queryString,500,500,null,null);
BufferedImagegrayImage=QrcodeUtils.grayImage(bufferedImage);
ImageIO.write(grayImage,"png",response.getOutputStream());
}
}
2、PayService
packagecom.qcsoft.payment.service.impl;
importcom.alibaba.fastjson.JSON;
importcom.alipay.api.AlipayClient;
importcom.qcsoft.commonbean.bean.common.KafkaConstant;
importcom.qcsoft.commonbean.bean.payment.ChinaumsConfig;
importcom.qcsoft.commonbean.bean.payment.PayLog;
importcom.qcsoft.commonbean.bean.payment.common.PayConstant;
importcom.qcsoft.commonbean.bean.payment.common.PrePayResult;
importcom.qcsoft.commonbean.bean.payment.common.WxPrePayResultPackage;
importcom.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
importcom.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayUnifiedOrderRequest;
importcom.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayUnifiedOrderResult;
importcom.qcsoft.commonbean.bean.payment.wx.config.WxPayConfig;
importcom.qcsoft.easyqinyutools.utils.JsonUtil;
importcom.qcsoft.payment.commns.exception.BaseException;
importcom.qcsoft.payment.commns.exception.QYError;
importcom.qcsoft.payment.commns.utils.UserUtil;
importcom.qcsoft.payment.commns.utils.weixin.PackageUtil;
importcom.qcsoft.payment.service.*;
importorg.apache.commons.lang3.StringUtils;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.stereotype.Service;
importjava.util.SortedMap;
importjava.util.TreeMap;
@Service
publicclassPayServiceImplimplementsPayService{
publicLoggerlogger=LoggerFactory.getLogger(getClass());
@Autowired
privateAliPayServicealiPayService;
@Autowired
privateWxPayServicewxPayService;
@Autowired
privateChinaumsPayServicechinaumsPayService;
@Autowired
privateUserUtiluserUtil;
@Autowired
privatePayLogServicepayLogService;
@Override
publicPrePayResultpayPreOrder(PreOrderParamorderParam)throwsBaseException{
logger.info("PayServiceImpl.payPreOrder---->>>>\n准备下单.....,当前用户订单号[{}]",orderParam.getDh());
Stringtemp="";
PrePayResultpayResult=newPrePayResult();
//校验支付方式
StringpayType=orderParam.getPayType();
if(!StringUtils.isNotBlank(payType))
thrownewBaseException(QYError.msg("请选择支付方式!"));
if(PayConstant.WXPAY.toString().equals(payType)){
//查询商家配置信息
WxPayConfigconfig;
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());
}
WxPayUnifiedOrderRequestrequestParam=wxPayService.packRequestParam(orderParam);
//开始请求预支付接口
WxPayUnifiedOrderResultresult=wxPayService.wxPrePay(config,requestParam);
//根据支付类型设置值
WxPrePayResultPackageresultPackage=null;
if(orderParam.getTradeType().equals(PayConstant.APP.toString())||orderParam.getTradeType().equals(PayConstant.JSAPI.toString())||orderParam.getTradeType().equals(PayConstant.WECHATAPP.toString())){
resultPackage=newWxPrePayResultPackage();
StringtimeMillis=PackageUtil.getTimeStamp();
StringnonceString=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())){
SortedMapreturnData=PackageUtil.getReturnData(resultPackage,config.getMchId());
Stringpaysign=PackageUtil.createSign(returnData,config.getMchKey());
resultPackage.setPaySign(paysign);
resultPackage.setInfoPackage(returnData.get("package"));
payResult.setWxAppPackage(resultPackage);
}else{
SortedMappaypackageParams=newTreeMap();
paypackageParams.put("appId",result.getAppid());//appid
paypackageParams.put("timeStamp",timeMillis);//
paypackageParams.put("nonceStr",nonceString);//
paypackageParams.put("package",resultPackage.getInfoPackage());//
paypackageParams.put("signType",resultPackage.getSignType());
Stringpaysign=PackageUtil.createSign(paypackageParams,config.getMchKey());
resultPackage.setPaySign(paysign);
payResult.setWxJsapiPackage(resultPackage);
}
}elseif(orderParam.getTradeType().equals(PayConstant.MWEB.toString())){
payResult.setWxH5Url(result.getMwebUrl()+"&redirect_url="+orderParam.getRedirectUrl());
}elseif(orderParam.getTradeType().equals(PayConstant.NATIVE.toString())){
payResult.setWxNativeUrl(result.getCodeURL());
}
//添加支付日志
insertPayLog(orderParam,KafkaConstant.PAYMENT_NOTIFY_001.getTopic(),"0",resultPackage,JSON.toJSONString(config));
returnpayResult;
}elseif(PayConstant.ALIPAY.toString().equals(payType)){
AlipayClientclient=aliPayService.getAlipayClientByAppCode(orderParam.getAppCode());
if(orderParam.getTradeType().equals(PayConstant.APP.toString())){
temp=aliPayService.aliAppPay(client,orderParam);
payResult.setAlipayAppParamStr(temp);
}elseif(orderParam.getTradeType().equals(PayConstant.MWEB.toString())){
temp=aliPayService.aliH5Pay(client,orderParam);
payResult.setAlipayH5Form(temp);
}elseif(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())));
returnpayResult;
}elseif(PayConstant.WECHATAPP.toString().equals(payType)){
}elseif(PayConstant.CHINAUMS.toString().equals(payType)){//银联pos支付
//查询商家配置信息
ChinaumsConfigconfig;
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));
returnpayResult;
}
logger.warn("用户未选择正确的支付方式");
thrownewBaseException(QYError.msg("请选择正确的支付方式!"));
}
publicvoidinsertPayLog(PreOrderParamorderParam,Stringtopic,StringmoneyType,Objectobj,StringpayConfigJsonStr){
PayLogpayLog=newPayLog();
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
packagecom.qcsoft.payment.service;
importcom.alipay.api.AlipayClient;
importcom.alipay.api.request.AlipayTradeRefundRequest;
importcom.alipay.api.response.AlipayTradeQueryResponse;
importcom.alipay.api.response.AlipayTradeRefundResponse;
importcom.qcsoft.commonbean.bean.payment.AlipayConfig;
importcom.qcsoft.commonbean.bean.payment.alipay.AliPayRefundParam;
importcom.qcsoft.commonbean.bean.payment.common.PayNotify;
importcom.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
importcom.qcsoft.easyqinyutools.message.ReturnMsg;
importjavax.servlet.http.HttpServletRequest;
importjava.util.Map;
publicinterfaceAliPayService{
/**
*
*@paramalipayClient
*@paramorderParam
*@param
*@return
*/
StringaliAppPay(AlipayClientalipayClient,PreOrderParamorderParam);
StringaliScanPay(AlipayClientalipayClient,PreOrderParamorderParam);
StringaliH5Pay(AlipayClientalipayClient,PreOrderParamorderParam);
voidaliPayNotify(PayNotifyparams);
booleanrsaCheckV1(HttpServletRequestrequest,StringappCode);
AlipayTradeQueryResponsealiPayOrderQuery(AlipayClientalipayClient,Stringout_trade_no);
AlipayClientgetAlipayClientByAppCode(StringappCode);
AlipayConfiggetConfigByAppCode(StringappCode);
/**
*支付宝退款接口
*@paramaliPayRefundParam
*@return
*/
ReturnMsgaliPayRefund(AliPayRefundParamaliPayRefundParam);
}
AliPayServiceImpl
packagecom.qcsoft.payment.service.impl;
importcom.alibaba.fastjson.JSON;
importcom.alipay.api.AlipayApiException;
importcom.alipay.api.AlipayClient;
importcom.alipay.api.DefaultAlipayClient;
importcom.alipay.api.domain.AlipayTradeAppPayModel;
importcom.alipay.api.domain.AlipayTradePrecreateModel;
importcom.alipay.api.domain.AlipayTradeRefundModel;
importcom.alipay.api.domain.AlipayTradeWapPayModel;
importcom.alipay.api.internal.util.AlipaySignature;
importcom.alipay.api.request.*;
importcom.alipay.api.response.*;
importcom.qcsoft.commonbean.bean.payment.AlipayConfig;
importcom.qcsoft.commonbean.bean.payment.alipay.AliPayRefundParam;
importcom.qcsoft.commonbean.bean.payment.common.PayConstant;
importcom.qcsoft.commonbean.bean.payment.common.PayNotify;
importcom.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
importcom.qcsoft.easyqinyutools.message.ReturnMsg;
importcom.qcsoft.payment.commns.exception.BaseException;
importcom.qcsoft.payment.commns.exception.QYError;
importcom.qcsoft.payment.commns.utils.DateUtils;
importcom.qcsoft.payment.commns.utils.RedisUtil;
importcom.qcsoft.payment.service.AliPayService;
importcom.qcsoft.payment.service.AlipayConfigService;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.stereotype.Service;
importjavax.servlet.http.HttpServletRequest;
importjava.net.URLEncoder;
importjava.util.Date;
importjava.util.HashMap;
importjava.util.Iterator;
importjava.util.Map;
/**
*支付宝相关业务实现类
*/
@Service
publicclassAliPayServiceImplimplementsAliPayService{
privatestaticfinalLoggerlogger=LoggerFactory.getLogger(AliPayServiceImpl.class);
@Autowired
privateAlipayConfigServicealipayConfigService;
@Autowired
privateRedisUtilredisUtil;
@Value("${payNotifyUrl}")
privateStringnotifyUrl;
/**
*APP支付
*参数加签
*/
@Override
publicStringaliAppPay(AlipayClientalipayClient,PreOrderParamorderParam){
logger.info("AliPayServiceImpl.aliAppPay--->>>\n支付宝预支付开始,\n支付类型为:APP支付,\n订单号为:{}",orderParam.getDh());
Datedate=newDate();
AlipayTradeAppPayResponseresponse=null;
//发起App支付请求
AlipayTradeAppPayModelmodel=newAlipayTradeAppPayModel();
//订单描述
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());
AlipayTradeAppPayRequestrequest=newAlipayTradeAppPayRequest();
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(AlipayApiExceptione){
logger.info("AliPayServiceImpl.aliAppPay----->\n支付宝预下单失败,\n本次下单的订单号为:{},\n相关报错信息为:{}",orderParam.getDh(),response,e);
thrownewBaseException(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());
thrownewBaseException(QYError.msg("调用支付宝预下单接口失败!["+response.getMsg()+"]"));
}
returnresponse.getBody();
}
/**
*扫码支付
*参数加签
*/
@Override
publicStringaliScanPay(AlipayClientalipayClient,PreOrderParamorderParam){
logger.info("AliPayServiceImpl.aliScanPay--->>>\n支付宝预支付开始,\n支付类型为:扫码支付,\n订单号:{}",orderParam.getDh());
/*AlipayTradePagePayResponseresponse=null;*/
AlipayTradePrecreateResponseresponse=null;
Datedate=newDate();
/**
*设置请求model参数(body、subject、outTradeNo、totalAmount、timeoutExpress;必传)
*/
AlipayTradePrecreateModelmodel=newAlipayTradePrecreateModel();
//订单描述
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());
//选填
/**
*创建支付宝扫码支付请求接口类,设置相关请求处理信息,准备请求下单
*/
AlipayTradePrecreateRequestrequest=newAlipayTradePrecreateRequest();
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(AlipayApiExceptione){
logger.info("AliPayServiceImpl.aliScanPay----->\n支付宝预下单失败,\n本次下单的订单号:{},\n相关报错信息为:{}",orderParam.getDh(),response,e);
thrownewBaseException(QYError.msg("调用支付宝预下单接口失败!["+e.getMessage()+"]"));
}catch(Exceptione){
e.printStackTrace();
thrownewBaseException(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());
thrownewBaseException(QYError.msg("调用支付宝预下单接口失败!["+response.getMsg()+"]"));
}
returnresponse.getQrCode();
}
/**
*H5支付
*参数加签
*/
@Override
publicStringaliH5Pay(AlipayClientalipayClient,PreOrderParamorderParam){
logger.info("AliPayServiceImpl.aliH5Pay--->>>\n支付宝预支付开始,\n支付类型为:H5支付,\n订单号:{}",orderParam.getDh());
Stringform="";
AlipayTradeWapPayResponseresponse=null;
/**
*封装请求支付信息
*/
AlipayTradeWapPayModelpayModel=newAlipayTradeWapPayModel();
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支付请求接口类,设置相关请求处理信息,准备请求下单
*/
AlipayTradeWapPayRequestalipay_request=newAlipayTradeWapPayRequest();
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));
thrownewBaseException(QYError.msg("支付宝"));
}
}catch(AlipayApiExceptione){
logger.info("AliPayServiceImpl.aliH5Pay----->>>>\n支付宝预支付接口返回信息:{}",JSON.toJSONString(response));
thrownewBaseException(QYError.msg("调用支付宝预下单接口失败!["+e.getMessage()+"]"));
}
logger.info("AliPayServiceImpl.aliH5Pay----->>>>\n支付宝预支付接口返回信息:{}",JSON.toJSONString(response));
/**
*打印日志,并返回链接
*/
returnform;
}
/**
*支付宝通知
*
*@paramparams
*/
@Override
publicvoidaliPayNotify(PayNotifyparams){
logger.info("AliPayServiceImpl.appAliPayNotify-\n阿里服务器消费手机回调参数获取和参数判断-------》》》");
/**
*打印信息
*/
//校验支付金额
/*ReturnMsgreturnMsg=restTemplate.postForEntity(params.getNoOrderAmountUrl(),params,ReturnMsg.class).getBody();
if(!returnMsg.isSuccess()){
logger.info("WxPayController.wxPayNotify-->\n校验订单金额失败,请核实商务订单号:{}",params);
thrownewBaseException(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());
thrownewBaseException(QYError.msg("支付宝支付失败!商务订单号["+params.getOutTradeNo()+"]"));
}
}
@Override
publicbooleanrsaCheckV1(HttpServletRequestrequest,StringappCode){
//获取支付宝GET过来反馈信息
Mapparams=newHashMap();
//签名验证(对支付宝返回的数据验证,确定是支付宝返回的)
booleanresult=false;
try{
//从支付宝回调的request域中取值
MaprequestParams=request.getParameterMap();
for(Iteratoriter=requestParams.keySet().iterator();iter.hasNext();){
Stringname=iter.next();
String[]values=(String[])requestParams.get(name);
StringvalueStr="";
for(inti=0;i>>>>>>>>>>>>>>{}",JSON.toJSONString(params));
//商家编码
AlipayConfigalipayConfig=getConfigByAppCode(appCode);
result=AlipaySignature.rsaCheckV1(params,alipayConfig.getAliPublicKey(),
PayConstant.ALIPAY_CHARSET.getKey(),PayConstant.ALIPAY_SIGN_TYPE_RSA2.getKey());
}catch(Exceptione){
logger.error("AliPayServiceImpl.appAliPayNotify---\n校验签名失败!商务订单号[{}]---->>",JSON.toJSONString(request),e);
thrownewBaseException(QYError.msg("支付宝支付校验签名失败!"));
}
returnresult;
}
/**
*根据商务订单号查询查询支付信息
*
*@paramalipayClient
*@paramout_trade_no
*@return
*/
@Override
publicAlipayTradeQueryResponsealiPayOrderQuery(AlipayClientalipayClient,Stringout_trade_no){
logger.info("AliPayServiceImpl.aliPayOrderQuery----\n根据商务订单号查询支付宝订单信息,\n商务订单号:[{}]----》》》",out_trade_no);
AlipayTradeQueryResponseresponse=null;
AlipayTradeQueryRequestrequest=newAlipayTradeQueryRequest();
//设置查询参数
MapbizModel=newHashMap<>();
bizModel.put("out_trade_no",out_trade_no);
request.setBizContent(JSON.toJSONString(bizModel));
//开始查询
try{
response=alipayClient.execute(request);
}catch(AlipayApiExceptione){
logger.error("AliPayServiceImpl.aliPayOrderQuery--->>\n支付宝订单查询失败,\n商务订单号:[{}]",out_trade_no);
thrownewBaseException(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);
thrownewBaseException(QYError.msg("订单号["+out_trade_no+"],订单支付失败,状态码为["+response.getTradeStatus()+"]"));
}
returnresponse;
}
/**
*根据商家编码设置alipay配置信息
*
*@paramappCode商家编码
*@return
*/
@Override
publicAlipayClientgetAlipayClientByAppCode(StringappCode){
logger.info("AliPayServiceImpl.getAlipayClientByAppCode--->>\n获取支付宝配置信息:[{}]",appCode);
AlipayConfigalipayConfig=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);
thrownewBaseException(QYError.msg("获取支付宝支付配置信息失败!"));
}
}catch(Exceptione){
logger.error("AliPayServiceImpl.getAlipayClientByAppCode--->>\n获取支付宝配置信息失败:[{}]",e);
thrownewBaseException(QYError.msg("获取支付宝配置信息失败!"));
}
AlipayClientalipayClient=newDefaultAlipayClient(
PayConstant.ALIPAY_01.getKey(),
alipayConfig.getAliAppid(),
alipayConfig.getAliPrivateKey(),
PayConstant.ALIPAY_FORMAT.getKey(),
PayConstant.ALIPAY_CHARSET.getKey(),
alipayConfig.getAliPublicKey(),
PayConstant.ALIPAY_SIGN_TYPE_RSA2.getKey());
returnalipayClient;
}
//获取商家支付宝的配置信息
publicAlipayConfiggetConfigByAppCode(StringappCode){
AlipayConfigalipayConfig=alipayConfigService.selectByAppCode(appCode);
returnalipayConfig;
}
/**
*支付宝退款接口
*@paramaliPayRefundParam
*@return
*/
publicReturnMsgaliPayRefund(AliPayRefundParamaliPayRefundParam){
ReturnMsgreturnMsg=newReturnMsg();
StringappCode=aliPayRefundParam.getAppCode();
AlipayClientalipayClient=getAlipayClientByAppCode(appCode);
AlipayTradeRefundResponseresponse=null;
AlipayTradeRefundModelmodel=newAlipayTradeRefundModel();
//订单支付时传入的商户订单号,不能和trade_no同时为空。
model.setOutTradeNo(aliPayRefundParam.getOutTradeNo());
//支付宝交易号,和商户订单号不能同时为空
//model.setTradeNo(aliPayRefundParam.getTradeNo());
//标识一次退款请求,同一笔交易多次退款需要保证唯一,如需部分退款,则此参数必传。
model.setOutRequestNo(aliPayRefundParam.getOutRequestNo());
// 需要退款的金额,该金额不能大于订单金额,单位为元,支持两位小数
model.setRefundAmount(aliPayRefundParam.getRefundAmount());
//退款的原因说明
model.setRefundReason(aliPayRefundParam.getRefundReason());
/**
*创建支付宝扫码支付请求接口类,设置相关请求处理信息,准备请求下单
*/
AlipayTradeRefundRequestrequest=newAlipayTradeRefundRequest();
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(AlipayApiExceptione){
logger.info("支付宝退款失败,\n本次下单的订单号:{},\n相关报错信息为:{}",aliPayRefundParam.getDh(),response,e);
thrownewBaseException(QYError.msg("调用支付宝预退款失败!["+e.getMessage()+"]"));
}catch(Exceptione){
e.printStackTrace();
thrownewBaseException(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());
returnreturnMsg.setData("退款成功");
}else{
logger.error("AliPayServiceImpl.aliScanPay----->\n调用支付宝退款接口失败!\n具体信息:\n{}",response.getBody());
thrownewBaseException(QYError.msg("调用支付宝退款接口失败!["+response.getBody()+"]"));
}
}
}
4、WxPayService
packagecom.qcsoft.payment.service;
importcom.qcsoft.commonbean.bean.payment.WxMinConfig;
importcom.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
importcom.qcsoft.commonbean.bean.payment.wx.bean.WxRefund;
importcom.qcsoft.commonbean.bean.payment.wx.bean.entpay.EntPayParam;
importcom.qcsoft.commonbean.bean.payment.wx.bean.entpay.EntPayResult;
importcom.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayUnifiedOrderRequest;
importcom.qcsoft.commonbean.bean.payment.wx.bean.result.BaseWxPayResult;
importcom.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayOrderQueryResult;
importcom.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayUnifiedOrderResult;
importcom.qcsoft.commonbean.bean.payment.wx.config.WxPayConfig;
importcom.qcsoft.commonbean.bean.payment.wx.exception.WxPayException;
/**
*微信预支付
*@paramappId应用ID(微信公众号)
*@parammchId商务号ID
*@parammchKey商务号密钥
*@paramnotifyUrl异步通知地址
*@paramsignType签名类型
*@parambody描述
*@paramtotalFee金额
*@paramspbillCreateIpapp和h5支付需要用户的真实请求地址
*@paramtradeType
*@paramoutTradeNo
*@return
*/
publicinterfaceWxPayService{
/**
*
*@paramconfig{appId:应用ID,mchId:商务号ID,mchKey:商务号密钥,notifyUrl:异步通知地址,signType:签名类型}
*@paramrequest{body:订单描述,totalFee:金额,
*spbillCreateIp:app和h5支付需要用户的真实请求地址Native支付填调用微信支付API的机器IP,
*tradeType:SAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里,
*outTradeNo:商户订单号,productId:商品Id(扫码支付必传,其他选填),openid:公众号openId}
*@return
*/
WxPayUnifiedOrderResultwxPrePay(WxPayConfigconfig,WxPayUnifiedOrderRequestrequest);
/**
*根据appCode获取商家微信支付配置
*@paramappCode
*@return
*/
WxPayConfiggetWxPayConfigByAppCode(StringappCode,StringbmCode);
WxPayConfiggetWxMinPayConfigByAppCode(StringappCode,StringsysSoftwareCode);
/**
*封装预下单参数实体
*@paramorderParam预支付接口参数实体
*@paramorder点单
*@return
*/
WxPayUnifiedOrderRequestpackRequestParam(PreOrderParamorderParam);
/**
*查询订单
*@paramappCode商家编码
*@paramdh订单号
*@paramsysSoftwareCode
*/
WxPayOrderQueryResultwxPayOrderQuery(StringappCode,StringbmCode,Stringdh,Integertype,StringsysSoftwareCode);
/**
*企业支付
*@paramparams
*@return:
*@Author:
*@date:
*/
BaseWxPayResultentPay(EntPayParamparams)throwsWxPayException;
}
WxPayServiceImpl
packagecom.qcsoft.payment.service.impl;
importcom.alibaba.fastjson.JSON;
importcom.qcsoft.commonbean.bean.payment.PayLog;
importcom.qcsoft.commonbean.bean.payment.WxConfig;
importcom.qcsoft.commonbean.bean.payment.WxMinConfig;
importcom.qcsoft.commonbean.bean.payment.common.PayConstant;
importcom.qcsoft.commonbean.bean.payment.common.PayNotify;
importcom.qcsoft.commonbean.bean.payment.wx.bean.PreOrderParam;
importcom.qcsoft.commonbean.bean.payment.wx.bean.entpay.*;
importcom.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayOrderQueryRequest;
importcom.qcsoft.commonbean.bean.payment.wx.bean.request.WxPayUnifiedOrderRequest;
importcom.qcsoft.commonbean.bean.payment.wx.bean.result.BaseWxPayResult;
importcom.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayOrderQueryResult;
importcom.qcsoft.commonbean.bean.payment.wx.bean.result.WxPayUnifiedOrderResult;
importcom.qcsoft.commonbean.bean.payment.wx.config.WxPayConfig;
importcom.qcsoft.commonbean.bean.payment.wx.exception.WxPayException;
importcom.qcsoft.commonbean.bean.payment.wx.handler.EntPayHandler;
importcom.qcsoft.commonbean.bean.payment.wx.handler.WxPayHandler;
importcom.qcsoft.commonbean.bean.payment.wx.handler.impl.EntPayHandlerImpl;
importcom.qcsoft.commonbean.bean.payment.wx.handler.impl.WxPayHandlerApacheHttpImpl;
importcom.qcsoft.payment.commns.exception.BaseException;
importcom.qcsoft.payment.commns.exception.QYError;
importcom.qcsoft.payment.commns.utils.DateUtils;
importcom.qcsoft.payment.commns.utils.RedisUtil;
importcom.qcsoft.payment.service.PayLogService;
importcom.qcsoft.payment.service.WxConfigService;
importcom.qcsoft.payment.service.WxMinConfigService;
importcom.qcsoft.payment.service.WxPayService;
importlombok.extern.slf4j.Slf4j;
importorg.apache.commons.lang3.StringUtils;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importorg.springframework.beans.factory.annotation.Autowired;
importorg.springframework.beans.factory.annotation.Value;
importorg.springframework.stereotype.Service;
importjava.math.BigDecimal;
importjava.util.Date;
@Service
@Slf4j
publicclassWxPayServiceImplimplementsWxPayService{
privatestaticfinalLoggerlogger=LoggerFactory.getLogger(WxPayServiceImpl.class);
@Value("${payNotifyUrl}")
privateStringnotifyUrl;
@Autowired
privateRedisUtilredisUtil;
@Autowired
privateWxConfigServicewxConfigService;
@Autowired
privateWxMinConfigServicewxMinConfigService;
@Autowired
privatePayLogServicepayLogService;
/**
*@paramconfig{appId:应用ID,mchId:商务号ID,mchKey:商务号密钥,notifyUrl:异步通知地址,signType:签名类型}
*@paramrequest{body:订单描述,totalFee:金额,
*spbillCreateIp:app和h5支付需要用户的真实请求地址Native支付填调用微信支付API的机器IP,
*tradeType:SAPI--公众号支付、NATIVE--原生扫码支付、APP--app支付,统一下单接口trade_type的传参可参考这里,
*outTradeNo:商户订单号,productId:商品Id(扫码支付必传,其他选填),openid:公众号openId}还有很多参数选填
*@return
*@throwsWxPayException
*/
@Override
publicWxPayUnifiedOrderResultwxPrePay(WxPayConfigconfig,WxPayUnifiedOrderRequestrequest){
logger.info("WxPayServiceImpl.wxPrePay--->>\n微信预支付,\n商务订单号:[{}]",request.getOutTradeNo());
WxPayHandlerwx=newWxPayHandlerApacheHttpImpl();
WxPayUnifiedOrderResultorderResult=null;
wx.setConfig(config);
log.info("WxPayUnifiedOrderResult={}",config.getNotifyUrl());
try{
orderResult=wx.unifiedOrder(request);
}catch(WxPayExceptione){
logger.error("WxPayServiceImpl.wxPrePay--->>\n微信预支付失败,\n商务订单号:[{}]",request.getOutTradeNo(),orderResult);
logger.error("异常信息{}",e.getMessage());
thrownewBaseException(QYError.msg("订单号["+request.getOutTradeNo()+"]预支付失败!"));
}
returnorderResult;
}
/**
*根据商家编码获取微信商户配置信息
*
*@paramappCode
*@return
*/
@Override
publicWxPayConfiggetWxPayConfigByAppCode(StringappCode,StringbmCode){
logger.info("WxPayServiceImpl.getWxPayConfigByAppCode--->>\n获取微信支付配置信息:appCode[{}],bmCode[{}]",appCode,bmCode);
WxConfigconfig=null;
WxPayConfigwxPayConfig=newWxPayConfig();
/**
*获取商家支付宝配置信息(优先级: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);
thrownewBaseException(QYError.msg("获取微信支付配置信息失败!"));
}
}catch(Exceptione){
logger.error("WxPayServiceImpl.getWxPayConfigByAppCode--->>\n获取微信支付配置信息失败:[{}]",e);
thrownewBaseException(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);
returnwxPayConfig;
}
@Override
publicWxPayConfiggetWxMinPayConfigByAppCode(StringappCode,StringsysSoftwareCode){
logger.error("WxPayServiceImpl.getWxMinPayConfigByAppCode--->>\n获取微信小程序支付配置信息:[{}]",appCode);
if(StringUtils.isBlank(sysSoftwareCode)){
sysSoftwareCode="store-service";
}
WxMinConfigconfig=null;
WxPayConfigwxPayConfig=newWxPayConfig();
/**
*获取商家支付宝配置信息(优先级: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);
thrownewBaseException(QYError.msg("获取微信支付配置信息失败!"));
}
}catch(Exceptione){
logger.error("WxPayServiceImpl.getWxMinPayConfigByAppCode--->>\n获取微信小程序支付配置信息失败:[{}]",e);
thrownewBaseException(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);
returnwxPayConfig;
}
/**
*封装预下单参数实体
*
*@paramorderParam预支付接口参数实体
*@paramorder点单
*@return
*/
@Override
publicWxPayUnifiedOrderRequestpackRequestParam(PreOrderParamorderParam){
Datedate=newDate();
BigDecimalparamAmount=newBigDecimal(orderParam.getTotalAmount().toString());
BigDecimalmultiplyNum=newBigDecimal("100");
WxPayUnifiedOrderRequestrequest=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());
PayNotifypayNotify=newPayNotify();
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());
returnrequest;
}
/**
*订单查询
*
*@paramappCode商家编码
*@paramdh订单号
*@paramsysSoftwareCode
*@return
*/
@Override
publicWxPayOrderQueryResultwxPayOrderQuery(StringappCode,StringbmCode,Stringdh,Integertype,StringsysSoftwareCode){
logger.info("WxPayServiceImpl.wxPayOrderQuery--->>\n微信订单查询,\n本次查询的商家编码为:[{}],商务订单号:[{}]",appCode,dh);
WxPayHandlerhandler=newWxPayHandlerApacheHttpImpl();
WxPayOrderQueryRequestrequest=newWxPayOrderQueryRequest();
WxPayOrderQueryResultqueryResult=null;
WxPayConfigconfig=null;
try{
PayLogpayLog=payLogService.selectByDh(dh);
if(payLog==null){
//商家的微信支付
if(type==null||type==1){
bmCode=null;
config=this.getWxPayConfigByAppCode(appCode,bmCode);
//部门的微信支付支付
}elseif(type==2){
config=this.getWxPayConfigByAppCode(appCode,bmCode);
//商家小程序支付
}elseif(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(WxPayExceptione){
logger.error("WxPayServiceImpl.wxPayOrderQuery--->>\n微信订单查询失败,\n商务订单号:[{}]",dh);
thrownewBaseException(QYError.msg("微信订单查询失败,商务订单号:[{}]"+dh+""));
}
returnqueryResult;
}
/**
*企业支付
*@paramparams
*@return:com.qcsoft.commonbean.bean.payment.wx.bean.result.BaseWxPayResult
*@Author:
*@date:
*/
@Override
publicBaseWxPayResultentPay(EntPayParamparams)throwsWxPayException{
WxPayHandlerwxPayHandler=newWxPayHandlerApacheHttpImpl();
WxPayConfigconfig=null;
EntPayResultresult=null;
EntPayBankResultbankResult=null;
if(params.getTradeType()!=null&¶ms.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){
EntPayRequestrequest=packEntPayRequest(params,config);
EntPayHandlerentPayHandler=newEntPayHandlerImpl(wxPayHandler);
result=entPayHandler.entPay(request);
returnresult;
}else{
EntPayBankRequestrequest=packEntPayBankRequest(params);
EntPayHandlerentPayHandler=newEntPayHandlerImpl(wxPayHandler);
bankResult=entPayHandler.payBank(request);
returnbankResult;
}
}
/**
*封装微信企业支付请求参数
*@paramparams
*@return:com.qcsoft.commonbean.bean.payment.wx.bean.entpay.EntPayRequest
*@Author:
*@date:
*/
publicEntPayRequestpackEntPayRequest(EntPayParamparams,WxPayConfigconfig){
EntPayRequestrequest=newEntPayRequest();
request.setAmount