@@ -1,50 +1,10 @@
package com.jsowell.pile.service.impl ;
import com.alibaba.fastjson2.JSON ;
import com.alibaba.fastjson2.JSONObject ;
import com.fasterxml.jackson.core.JsonProcessingException ;
import com.fasterxml.jackson.databind.ObjectMapper ;
import com.google.common.collect.Maps ;
import com.jsowell.common.enums.MemberWalletEnum ;
import com.jsowell.common.enums.weixin.WeiXinPayTradeStatus ;
import com.jsowell.common.enums.ykc.ActionTypeEnum ;
import com.jsowell.common.enums.ykc.PayModeEnum ;
import com.jsowell.common.enums.ykc.PaymentInstitutionsEnum ;
import com.jsowell.common.enums.ykc.ScenarioEnum ;
import com.jsowell.common.util.DateUtils ;
import com.jsowell.common.util.StringUtils ;
import com.jsowell.common.util.id.SnowflakeIdWorker ;
import com.jsowell.pile.domain.MemberTransactionRecord ;
import com.jsowell.pile.domain.WxpayCallbackRecord ;
import com.jsowell.pile.domain.WxpayRefundCallback ;
import com.jsowell.pile.dto.PaymentScenarioDTO ;
import com.jsowell.pile.dto.WeixinPayDTO ;
import com.jsowell.pile.service.MemberBasicInfoService ;
import com.jsowell.pile.service.MemberTransactionRecordService ;
import com.jsowell.pile.service.WechatPayService ;
import com.jsowell.pile.service.WxpayCallbackRecordService ;
import com.jsowell.pile.service.WxpayRefundCallbackService ;
import com.jsowell.pile.vo.web.UpdateMemberBalanceDTO ;
import com.jsowell.wxpay.common.WeChatPayParameter ;
import com.jsowell.wxpay.response.WechatPayNotifyParameter ;
import com.jsowell.wxpay.response.WechatPayNotifyResource ;
import com.jsowell.wxpay.response.WechatPayRefundNotifyResource ;
import com.jsowell.wxpay.response.WechatPayRefundRequest ;
import com.jsowell.wxpay.response.WechatPayRefundResponse ;
import com.jsowell.wxpay.utils.AesUtil ;
import com.jsowell.wxpay.utils.HttpUtils ;
import com.jsowell.wxpay.utils.WechatPayUtils ;
import com.jsowell.pile.service.* ;
import lombok.extern.slf4j.Slf4j ;
import org.springframework.beans.factory.annotation.Autowired ;
import org.springframework.stereotype.Service ;
import javax.servlet.http.HttpServletRequest ;
import java.math.BigDecimal ;
import java.math.RoundingMode ;
import java.security.cert.X509Certificate ;
import java.util.HashMap ;
import java.util.Map ;
/**
* 微信支付
*/
@@ -64,58 +24,58 @@ public class WechatPayServiceImpl implements WechatPayService {
@Autowired
private MemberTransactionRecordService memberTransactionRecordService ;
@Override
public Map < String , Object > weixinPayV3( WeixinPayDTO dto ) throws Exception {
String openId = dto . getOpenId( ) ;
//封装请求参数
Map < String , Object > paramMap = new HashMap < > ( ) ;
// 支付的产品(小程序或者公众号,主要需要和微信支付绑定哦)
paramMap. put ( " appid " , WeChatPayParameter. appId ) ;
// 支付的商户号
paramMap. put ( " mchid " , WeChatPayParameter. mchId ) ;
// 商品描述
paramMap. put ( " description " , dto . getDescription( ) ) ;
// 商户订单号
paramMap. put ( " out_trade_no" , SnowflakeIdWorker. getSnowflakeId( ) ) ;
// 交易结束时间
paramMap. put ( " time_expire " , getTimeExpire( ) ) ;
// 附加数据
paramMap. put ( " attach " , dto . getAttach ( ) ) ;
// 通知地址
paramMap. put ( " notify_url " , WeChatPayParameter. notifyUrl) ;
Map < String , Object > amountMap = Maps . newHashMap( ) ;
//订单金额 单位分
amountMap. put ( " total " , Integer. parseInt( getMoney( dto . getAmount ( ) ) ) ) ;
amountMap. put ( " currency " , " CNY " ) ;
paramMap. put ( " amount " , amountMap) ;
// 设置小程序所需的openid
Map < String , Object > payerMap = Maps . newHashMap( ) ;
payerMap. put ( " openid " , openId) ;
paramMap. put ( " payer " , payerMap) ;
ObjectMapper objectMapper = new ObjectMapper( ) ;
String body = objectMapper. writeValueAsString( paramMap) ;
log . info ( " 支付的相关参数是:{} " , body ) ;
Map < String , Object > stringObjectMap = HttpUtils. doPostWexin( WeChatPayParameter. unifiedOrderUrlJS, body ) ;
try {
return WechatPayUtils. getTokenWeixin( WeChatPayParameter. appId , String. valueOf( stringObjectMap. get ( " prepay_id " ) ) ) ;
} catch ( Exception e ) {
log . error ( " 微信支付v3 error " , e ) ;
}
return null ;
}
// @Override
// public Map<String, Object> weixinPayV3( WeixinPayDTO dto) throws Exception {
// String openId = dto. getOpenId() ;
// // 封装请求参数
// Map<String, Object> paramMap = new HashMap<>() ;
// // 支付的产品(小程序或者公众号,主要需要和微信支付绑定哦)
// paramMap.put("appid", WeChatPayParameter.appId) ;
// // 支付的商户号
// paramMap.put("mchid", WeChatPayParameter.mchId) ;
// // 商品描述
// paramMap.put("description", dto. getDescription()) ;
// // 商户订单号
// paramMap.put(" out_trade_no", SnowflakeIdWorker. getSnowflakeId()) ;
// // 交易结束时间
// paramMap.put("time_expire", getTimeExpire()) ;
// // 附加数据
// paramMap.put("attach", dto.getAttach()) ;
// // 通知地址
// paramMap.put("notify_url", WeChatPayParameter. notifyUrl) ;
//
// Map<String, Object> amountMap = Maps. newHashMap() ;
// // 订单金额 单位分
// amountMap.put("total", Integer. parseInt( getMoney(dto.getAmount()))) ;
// amountMap.put("currency", "CNY") ;
// paramMap.put("amount", amountMap) ;
// // 设置小程序所需的openid
// Map<String, Object> payerMap = Maps. newHashMap() ;
// payerMap.put("openid", openId) ;
// paramMap.put("payer", payerMap) ;
//
// ObjectMapper objectMapper = new ObjectMapper() ;
// String body = objectMapper. writeValueAsString( paramMap) ;
// log.info("支付的相关参数是:{}", body) ;
//
// Map<String, Object> stringObjectMap = HttpUtils. doPostWexin( WeChatPayParameter. unifiedOrderUrlJS, body) ;
// try {
// return WechatPayUtils. getTokenWeixin( WeChatPayParameter.appId, String. valueOf( stringObjectMap.get("prepay_id"))) ;
// } catch (Exception e) {
// log.error("微信支付v3 error", e) ;
// }
// return null;
// }
/**
* 获取过期时间
* @return
*/
private String getTimeExpire( ) {
long currentTimeMillis = System. currentTimeMillis( ) ;
currentTimeMillis = currentTimeMillis + ( 30 * 60 * 1000 ) ;
return DateUtils. timeStampToRfc3339( currentTimeMillis) ;
}
// private String getTimeExpire() {
// long currentTimeMillis = System. currentTimeMillis() ;
// currentTimeMillis = currentTimeMillis + (30 * 60 * 1000) ;
// return DateUtils. timeStampToRfc3339( currentTimeMillis) ;
// }
/**
* 元转换成分
@@ -123,53 +83,53 @@ public class WechatPayServiceImpl implements WechatPayService {
* @param amount
* @return
*/
public static String getMoney( String amount) {
if ( amount = = null ) {
return " " ;
}
// 金额转化为分为单位
// 处理包含, ¥ 或者$的金额
String currency = amount. replaceAll( " \\ $| \\ ¥| \\ , " , " " ) ;
int index = currency. indexOf( " . " ) ;
int length = currency. length( ) ;
Long amLong = 0L ;
if ( index = = - 1 ) {
amLong = Long . valueOf( currency + " 00 " ) ;
} else if ( length - index > = 3 ) {
amLong = Long . valueOf ( ( currency. substring( 0 , index + 3 ) ) . replace ( " . " , " " ) ) ;
} else if ( length - index = = 2 ) {
amLong = Long . valueOf ( ( currency. substring( 0 , index + 2 ) ) . replace ( " . " , " " ) + 0 ) ;
} else {
amLong = Long . valueOf ( ( currency. substring( 0 , index + 1 ) ) . replace ( " . " , " " ) + " 00 " ) ;
}
return amLong. toString( ) ;
}
// public static String getMoney( String amount) {
// if (amount == null) {
// return "" ;
// }
// // 金额转化为分为单位
// // 处理包含, ¥ 或者$的金额
// String currency = amount. replaceAll("\\$|\\¥|\\,", "") ;
// int index = currency. indexOf(".") ;
// int length = currency. length() ;
// Long amLong = 0L ;
// if (index == -1) {
// amLong = Long. valueOf( currency + "00") ;
// } else if (length - index >= 3) {
// amLong = Long.valueOf(( currency. substring(0, index + 3)).replace(".", "")) ;
// } else if (length - index == 2) {
// amLong = Long.valueOf(( currency. substring(0, index + 2)).replace(".", "") + 0) ;
// } else {
// amLong = Long.valueOf(( currency. substring(0, index + 1)).replace(".", "") + "00") ;
// }
// return amLong. toString() ;
// }
public static void main ( String [ ] args ) {
String s = " { \ n " +
" \" mchid \" : \" 1632405339 \" , \ n " +
" \" appid \" : \" wxbb3e0d474569481d \" , \ n " +
" \" out_trade_no \" : \" 823422832569454592 \" , \ n " +
" \" transaction_id \" : \" 4200001841202305301676160680\" , \ n " +
" \" trade_type \" : \" JSAPI \" , \ n " +
" \" trade_state \" : \" SUCCESS \" , \ n " +
" \" trade_state_desc \" : \" 支付成功 \" , \ n " +
" \" bank_type \" : \" OTHERS \" , \ n " +
" \" attach \" : \" { \\ \" memberId \\ \" : \\ \" 82507801 \\ \" , \\ \" orderCode \\ \" : \\ \" C27473779928 \\ \" , \\ \" type \\ \" : \\ \" order \\ \" } \" , \ n " +
" \" success_time \" : \" 2023-05-30T15:15:20+08:00\" , \ n " +
" \" payer \" : { \ n " +
" \" openid \" : \" o4REX5FPLsLOxM2x9ig2MHuuHPqU\" \ n " +
" }, \ n " +
" \" amount \" : { \ n " +
" \" total \" : 5000, \ n " +
" \" payer_total\" : 5000,\ n " +
" \" currency\" : \" CNY \" , \ n " +
" \" payer_currency\" : \" CNY \" \ n " +
" } \ n " +
" } " ;
WechatPayNotifyResource wechatPayNotifyResource = JSON . parseObject ( s , WechatPayNotifyResource. class ) ;
System . out . println( wechatPayNotifyResource) ;
}
// public static void main(String[] args) {
// String s = "{\n" +
// " \"mchid\": \"1632405339\",\n" +
// " \"appid\": \"wxbb3e0d474569481d\",\n" +
// " \"out_trade_no\": \"823422832569454592\",\n" +
// " \"transaction_id\": \" 4200001841202305301676160680\",\n" +
// " \"trade_type\": \"JSAPI\",\n" +
// " \"trade_state\": \"SUCCESS\",\n" +
// " \"trade_state_desc\": \"支付成功\",\n" +
// " \"bank_type\": \"OTHERS\",\n" +
// " \"attach\": \"{\\\"memberId\\\":\\\"82507801\\\",\\\"orderCode\\\":\\\"C27473779928\\\",\\\"type\\\":\\\"order\\\"}\",\n" +
// " \"success_time\": \" 2023-05-30T15:15:20+08:00\",\n" +
// " \"payer\": {\n" +
// " \"openid\": \" o4REX5FPLsLOxM2x9ig2MHuuHPqU\"\n" +
// " },\n" +
// " \"amount\": {\n" +
// " \"total\": 5000,\n" +
// " \" payer_total\" : 5000,\n" +
// " \" currency\": \"CNY\",\n" +
// " \" payer_currency\": \"CNY\"\n" +
// " }\n" +
// "}" ;
// WechatPayNotifyResource wechatPayNotifyResource = JSON.parseObject(s, WechatPayNotifyResource.class) ;
// System.out. println( wechatPayNotifyResource) ;
// }
/**
* 微信支付回调
@@ -178,88 +138,88 @@ public class WechatPayServiceImpl implements WechatPayService {
* @throws Exception
* @return
*/
@Override
public Map < String , Object > wechatPayCallbackInfo( HttpServletRequest request, WechatPayNotifyParameter body ) throws Exception {
Map < String , Object > resultMap = Maps . newHashMap( ) ;
//1: 获取微信支付回调的获取签名信息
String timestamp = request. getHeader( " Wechatpay-Timestamp" ) ;
String nonce = request. getHeader( " Wechatpay-Nonce" ) ;
ObjectMapper objectMapper = new ObjectMapper( ) ;
// 2: 开始解析报文体
String data = objectMapper. writeValueAsString( body ) ;
String message = timestamp + " \ n " + nonce + " \ n " + data + " \ n " ;
//3: 获取应答签名
String sign = request. getHeader( " Wechatpay-Signature" ) ;
//4: 获取平台对应的证书
String serialNo = request. getHeader( " Wechatpay-Serial" ) ;
if ( ! WeChatPayParameter. certificateMap. containsKey( serialNo) ) {
WeChatPayParameter. certificateMap = WechatPayUtils. refreshCertificate( ) ;
}
X509Certificate x509Certificate = WeChatPayParameter. certificateMap. get ( serialNo) ;
if ( ! WechatPayUtils. verify( x509Certificate, message. getBytes( ) , sign ) ) {
throw new IllegalArgumentException( " 微信支付签名验证失败:" + message) ;
}
// log.info("签名验证成功");
WechatPayNotifyParameter. Resource resource = body . getResource( ) ;
// 5: 回调报文解密
AesUtil aesUtil = new AesUtil( WeChatPayParameter. v3Key . getBytes ( ) ) ;
// 解密后json字符串
String decryptToString = aesUtil. decryptToString (
resource. getAssociated_data( ) . getBytes ( ) ,
resource. getNonce( ) . getBytes ( ) ,
resource. getCiphertext( ) ) ;
log . info ( " 2-->decryptToString====>{}" , decryptToString) ;
//6: 获取微信支付返回的信息
WechatPayNotifyResource wechatPayNotifyResource = JSON . parseObject( decryptToString, WechatPayNotifyResource. class ) ;
//7: 支付状态的判断 如果是success就代表支付成功
if ( StringUtils. equals( wechatPayNotifyResource. getTrade_state( ) , WeiXinPayTradeStatus. SUCCESS. getValue( ) ) ) {
// 8: 获取支付的交易单号, 流水号, 和附属参数
String out_trade_no = wechatPayNotifyResource. getOut_trade_no( ) ;
// 微信支付单号
String transaction_id = wechatPayNotifyResource. getTransaction_id( ) ;
String attach = wechatPayNotifyResource. getAttach( ) ;
log . info ( " 3-->微信支付成功,商户订单号是:{}, 支付订单号:{}, 附属参数是:{}" , out_trade_no, transaction_id, attach) ;
// 转换附属参数
PaymentScenarioDTO paymentScenarioDTO = JSONObject. parseObject( attach, PaymentScenarioDTO. class ) ;
String type = paymentScenarioDTO. getType( ) ;
//
BigDecimal amount = new BigDecimal( wechatPayNotifyResource. getAmount( ) . getTotal ( ) ) ;
if ( StringUtils. equals( type , ScenarioEnum . ORDER . getValue ( ) ) ) {
// 1-订单支付
resultMap. put ( " orderCode " , paymentScenarioDTO. getOrderCode( ) ) ;
resultMap. put ( " memberId " , paymentScenarioDTO. getMemberId( ) ) ;
resultMap. put ( " amount " , amount) ;
resultMap. put ( " type " , type ) ;
} else if ( StringUtils. equals( type , ScenarioEnum. BALANCE. getValue( ) ) ) {
// 2-充值余额
resultMap. put ( " memberId " , paymentScenarioDTO. getMemberId( ) ) ;
resultMap. put ( " amount " , amount) ;
resultMap. put ( " type " , type ) ;
}
resultMap. put ( " out_trade_no" , out_trade_no) ;
resultMap. put ( " transaction_id" , transaction_id) ;
// 保存微信支付记录
WxpayCallbackRecord record = new WxpayCallbackRecord( ) ;
record. setPayScenario( type ) ;
record. setMemberId( paymentScenarioDTO. getMemberId( ) ) ;
record. setOrderCode( paymentScenarioDTO. getOrderCode( ) ) ;
record. setOutTradeNo( out_trade_no) ;
record. setTransactionId( transaction_id) ;
record. setMchId( wechatPayNotifyResource. getMchid( ) ) ;
record. setAppId( wechatPayNotifyResource. getAppid( ) ) ;
record. setTradeType( wechatPayNotifyResource. getTrade_type( ) ) ;
record. setTradeState( wechatPayNotifyResource. getTrade_state( ) ) ;
record. setTradeStateDesc( wechatPayNotifyResource. getTrade_state_desc( ) ) ;
record. setBankType( wechatPayNotifyResource. getBank_type( ) ) ;
record. setAttach( wechatPayNotifyResource. getAttach( ) ) ;
record. setSuccessTime( DateUtils. toLocalDateTime( wechatPayNotifyResource. getSuccess_time( ) , DateUtils. RFC3339) ) ;
record. setPayerOpenId( wechatPayNotifyResource. getPayer( ) . getOpenid ( ) ) ;
record. setPayerTotal( wechatPayNotifyResource. getAmount( ) . getTotal ( ) ) ;
wxpayCallbackRecordService. insertSelective( record) ;
}
return resultMap ;
}
// @Override
// public Map<String, Object> wechatPayCallbackInfo( HttpServletRequest request, WechatPayNotifyParameter body) throws Exception {
// Map<String, Object> resultMap = Maps. newHashMap() ;
// // 1: 获取微信支付回调的获取签名信息
// String timestamp = request. getHeader(" Wechatpay-Timestamp") ;
// String nonce = request. getHeader(" Wechatpay-Nonce") ;
// ObjectMapper objectMapper = new ObjectMapper() ;
// // 2: 开始解析报文体
// String data = objectMapper. writeValueAsString(body) ;
// String message = timestamp + "\n" + nonce + "\n" + data + "\n" ;
// // 3: 获取应答签名
// String sign = request. getHeader(" Wechatpay-Signature") ;
// // 4: 获取平台对应的证书
// String serialNo = request. getHeader(" Wechatpay-Serial") ;
// if (! WeChatPayParameter. certificateMap. containsKey( serialNo)) {
// WeChatPayParameter. certificateMap = WechatPayUtils. refreshCertificate() ;
// }
// X509Certificate x509Certificate = WeChatPayParameter. certificateMap.get( serialNo) ;
// if (! WechatPayUtils. verify( x509Certificate, message. getBytes(), sign)) {
// throw new IllegalArgumentException(" 微信支付签名验证失败:" + message) ;
// }
// // log.info("签名验证成功");
// WechatPayNotifyParameter. Resource resource = body. getResource() ;
// // 5: 回调报文解密
// AesUtil aesUtil = new AesUtil( WeChatPayParameter.v3Key.getBytes()) ;
// // 解密后json字符串
// String decryptToString = aesUtil. decryptToString(
// resource. getAssociated_data().getBytes() ,
// resource. getNonce().getBytes() ,
// resource. getCiphertext()) ;
// log.info(" 2-->decryptToString====>{}", decryptToString) ;
//
// // 6: 获取微信支付返回的信息
// WechatPayNotifyResource wechatPayNotifyResource = JSON. parseObject( decryptToString, WechatPayNotifyResource.class) ;
// // 7: 支付状态的判断 如果是success就代表支付成功
// if ( StringUtils. equals( wechatPayNotifyResource. getTrade_state(), WeiXinPayTradeStatus. SUCCESS. getValue())) {
// // 8: 获取支付的交易单号, 流水号, 和附属参数
// String out_trade_no = wechatPayNotifyResource. getOut_trade_no() ;
// // 微信支付单号
// String transaction_id = wechatPayNotifyResource. getTransaction_id() ;
// String attach = wechatPayNotifyResource. getAttach() ;
// log.info(" 3-->微信支付成功,商户订单号是:{}, 支付订单号:{}, 附属参数是:{}", out_trade_no, transaction_id, attach) ;
// // 转换附属参数
// PaymentScenarioDTO paymentScenarioDTO = JSONObject. parseObject( attach, PaymentScenarioDTO.class) ;
// String type = paymentScenarioDTO. getType() ;
// //
// BigDecimal amount = new BigDecimal( wechatPayNotifyResource. getAmount().getTotal()) ;
// if ( StringUtils. equals(type, ScenarioEnum.ORDER.getValue())) {
// // 1-订单支付
// resultMap.put("orderCode", paymentScenarioDTO. getOrderCode()) ;
// resultMap.put("memberId", paymentScenarioDTO. getMemberId()) ;
// resultMap.put("amount", amount) ;
// resultMap.put("type", type) ;
// } else if ( StringUtils. equals(type, ScenarioEnum. BALANCE. getValue())) {
// // 2-充值余额
// resultMap.put("memberId", paymentScenarioDTO. getMemberId()) ;
// resultMap.put("amount", amount) ;
// resultMap.put("type", type) ;
// }
// resultMap.put(" out_trade_no", out_trade_no) ;
// resultMap.put(" transaction_id", transaction_id) ;
// // 保存微信支付记录
// WxpayCallbackRecord record = new WxpayCallbackRecord() ;
// record. setPayScenario(type) ;
// record. setMemberId( paymentScenarioDTO. getMemberId()) ;
// record. setOrderCode( paymentScenarioDTO. getOrderCode()) ;
// record. setOutTradeNo( out_trade_no) ;
// record. setTransactionId( transaction_id) ;
// record. setMchId( wechatPayNotifyResource. getMchid()) ;
// record. setAppId( wechatPayNotifyResource. getAppid()) ;
// record. setTradeType( wechatPayNotifyResource. getTrade_type()) ;
// record. setTradeState( wechatPayNotifyResource. getTrade_state()) ;
// record. setTradeStateDesc( wechatPayNotifyResource. getTrade_state_desc()) ;
// record. setBankType( wechatPayNotifyResource. getBank_type()) ;
// record. setAttach( wechatPayNotifyResource. getAttach()) ;
// record. setSuccessTime( DateUtils. toLocalDateTime( wechatPayNotifyResource. getSuccess_time(), DateUtils. RFC3339)) ;
// record. setPayerOpenId( wechatPayNotifyResource. getPayer().getOpenid()) ;
// record. setPayerTotal( wechatPayNotifyResource. getAmount().getTotal()) ;
// wxpayCallbackRecordService. insertSelective( record) ;
// }
// return resultMap;
// }
/**
* 获取微信退款回调信息
@@ -268,119 +228,119 @@ public class WechatPayServiceImpl implements WechatPayService {
* @param body
* @return
*/
@Override
public Map < String , Object > wechatPayRefundCallbackInfo( HttpServletRequest request, WechatPayNotifyParameter body ) throws Exception {
//1: 获取微信支付回调的获取签名信息
String timestamp = request. getHeader( " Wechatpay-Timestamp" ) ;
String nonce = request. getHeader( " Wechatpay-Nonce" ) ;
ObjectMapper objectMapper = new ObjectMapper( ) ;
// 2: 开始解析报文体
String data = objectMapper. writeValueAsString( body ) ;
String message = timestamp + " \ n " + nonce + " \ n " + data + " \ n " ;
//3: 获取应答签名
String sign = request. getHeader( " Wechatpay-Signature" ) ;
//4: 获取平台对应的证书
String serialNo = request. getHeader( " Wechatpay-Serial" ) ;
if ( ! WeChatPayParameter. certificateMap. containsKey( serialNo) ) {
WeChatPayParameter. certificateMap = WechatPayUtils. refreshCertificate( ) ;
}
X509Certificate x509Certificate = WeChatPayParameter. certificateMap. get ( serialNo) ;
if ( ! WechatPayUtils. verify( x509Certificate, message. getBytes( ) , sign ) ) {
throw new IllegalArgumentException( " 微信支付签名验证失败:" + message) ;
}
// log.info("签名验证成功");
WechatPayNotifyParameter. Resource resource = body . getResource( ) ;
// 5: 回调报文解密
AesUtil aesUtil = new AesUtil( WeChatPayParameter. v3Key . getBytes ( ) ) ;
// 解密后json字符串
String decryptToString = aesUtil. decryptToString (
resource. getAssociated_data( ) . getBytes ( ) ,
resource. getNonce( ) . getBytes ( ) ,
resource. getCiphertext( ) ) ;
log . info ( " 微信退款回调信息:{} " , decryptToString) ;
WechatPayRefundNotifyResource refundNotifyResource = JSONObject. parseObject( decryptToString, WechatPayRefundNotifyResource. class ) ;
if ( refundNotifyResource = = null ) {
return null ;
}
// 查询原支付信息,获取是订单结算退款还是余额退款
String out_trade_no = refundNotifyResource. getOut_trade_no( ) ;
String out_refund_no = refundNotifyResource. getOut_refund_no( ) ;
String transaction_id = refundNotifyResource. getTransaction_id( ) ;
String refund_id = refundNotifyResource. getRefund_id( ) ;
WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService. selectByOutTradeNo( out_trade_no) ;
if ( wxpayCallbackRecord = = null ) {
log . info ( " 查询原支付信息为空 OutTradeNo:{}" , out_trade_no) ;
return null ;
}
String memberId = wxpayCallbackRecord. getMemberId( ) ;
String orderCode = wxpayCallbackRecord. getOrderCode( ) ;
// 退款金额 单位分
int payer_refund = refundNotifyResource. getAmount( ) . getPayer_refund( ) ;
// 分转成元
BigDecimal refundAmount = new BigDecimal( payer_refund) . divide ( new BigDecimal ( 100 ) , 2 , RoundingMode. HALF_UP) ;
// 收到的退款回调是退余额的,扣除会员余额
if ( StringUtils. equals( wxpayCallbackRecord. getPayScenario( ) , ScenarioEnum. BALANCE. getValue( ) ) ) {
// 这笔支付订单原来是充值余额的,退款成功了,需要扣掉会员的本金金额
UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO( ) ;
dto . setMemberId( memberId) ;
dto . setUpdatePrincipalBalance( refundAmount) ; // 更新会员本金金额,单位元
dto . setType( MemberWalletEnum. TYPE_OUT. getValue( ) ) ;
dto . setSubType( MemberWalletEnum. SUBTYPE_USER_REFUND. getValue( ) ) ;
memberBasicInfoService. updateMemberBalance( dto ) ;
}
// 保存微信退款回调信息
WxpayRefundCallback record = WxpayRefundCallback. builder( )
. memberId( memberId )
. orderCode( orderCode )
. outTradeNo( out_trade_no )
. outRefundNo( out_refund_no )
. transactionId( transaction_id )
. mchId ( refundNotifyResource. getMchid( ) )
. refundId( refund_id )
. refundStatus( refundNotifyResource. getRefund_status( ) )
. successTime( refundNotifyResource. getSuccess_time( ) )
. userReceivedAccount( refundNotifyResource. getUser_received_account( ) )
. payerTotal( refundNotifyResource. getAmount( ) . getPayer_total( ) + " " )
. payerRefund( payer_refund + " " ) // 微信支付接收单位分
. amountTotal( refundNotifyResource. getAmount( ) . getTotal ( ) + " " )
. amountRefund( refundNotifyResource. getAmount( ) . getRefund ( ) + " " )
. build ( ) ;
wxpayRefundCallbackService. insertSelective( record) ;
// 记录会员交易流水
MemberTransactionRecord memberTransactionRecord = MemberTransactionRecord. builder( )
. orderCode( orderCode )
. scenarioType( wxpayCallbackRecord. getPayScenario( ) )
. memberId( memberId )
. actionType( ActionTypeEnum. REVERSE. getValue( ) )
. payMode( PayModeEnum. PAYMENT_OF_WECHATPAY. getValue( ) )
. paymentInstitutions( PaymentInstitutionsEnum. WECHAT_PAY. getValue( ) )
. amount( refundAmount) // 记录会员交易流水,单位元
. outTradeNo( out_trade_no )
. transactionId( transaction_id )
. outRefundNo( out_refund_no )
. refundId( refund_id )
. build ( ) ;
memberTransactionRecordService. insertSelective( memberTransactionRecord) ;
return null ;
}
// @Override
// public Map<String, Object> wechatPayRefundCallbackInfo( HttpServletRequest request, WechatPayNotifyParameter body) throws Exception {
// // 1: 获取微信支付回调的获取签名信息
// String timestamp = request. getHeader(" Wechatpay-Timestamp") ;
// String nonce = request. getHeader(" Wechatpay-Nonce") ;
// ObjectMapper objectMapper = new ObjectMapper() ;
// // 2: 开始解析报文体
// String data = objectMapper. writeValueAsString(body) ;
// String message = timestamp + "\n" + nonce + "\n" + data + "\n" ;
// // 3: 获取应答签名
// String sign = request. getHeader(" Wechatpay-Signature") ;
// // 4: 获取平台对应的证书
// String serialNo = request. getHeader(" Wechatpay-Serial") ;
// if (! WeChatPayParameter. certificateMap. containsKey( serialNo)) {
// WeChatPayParameter. certificateMap = WechatPayUtils. refreshCertificate() ;
// }
// X509Certificate x509Certificate = WeChatPayParameter. certificateMap.get( serialNo) ;
// if (! WechatPayUtils. verify( x509Certificate, message. getBytes(), sign)) {
// throw new IllegalArgumentException(" 微信支付签名验证失败:" + message) ;
// }
// // log.info("签名验证成功");
// WechatPayNotifyParameter. Resource resource = body. getResource() ;
// // 5: 回调报文解密
// AesUtil aesUtil = new AesUtil( WeChatPayParameter.v3Key.getBytes()) ;
// // 解密后json字符串
// String decryptToString = aesUtil. decryptToString(
// resource. getAssociated_data().getBytes() ,
// resource. getNonce().getBytes() ,
// resource. getCiphertext()) ;
// log.info("微信退款回调信息:{}", decryptToString) ;
//
// WechatPayRefundNotifyResource refundNotifyResource = JSONObject. parseObject( decryptToString, WechatPayRefundNotifyResource.class) ;
// if ( refundNotifyResource == null) {
// return null;
// }
// // 查询原支付信息,获取是订单结算退款还是余额退款
// String out_trade_no = refundNotifyResource. getOut_trade_no() ;
// String out_refund_no = refundNotifyResource. getOut_refund_no() ;
// String transaction_id = refundNotifyResource. getTransaction_id() ;
// String refund_id = refundNotifyResource. getRefund_id() ;
//
// WxpayCallbackRecord wxpayCallbackRecord = wxpayCallbackRecordService. selectByOutTradeNo( out_trade_no) ;
// if ( wxpayCallbackRecord == null) {
// log.info(" 查询原支付信息为空 OutTradeNo:{}", out_trade_no) ;
// return null;
// }
//
// String memberId = wxpayCallbackRecord. getMemberId() ;
// String orderCode = wxpayCallbackRecord. getOrderCode() ;
// // 退款金额 单位分
// int payer_refund = refundNotifyResource. getAmount(). getPayer_refund() ;
// // 分转成元
// BigDecimal refundAmount = new BigDecimal( payer_refund).divide(new BigDecimal(100), 2, RoundingMode. HALF_UP) ;
//
// // 收到的退款回调是退余额的,扣除会员余额
// if ( StringUtils. equals( wxpayCallbackRecord. getPayScenario(), ScenarioEnum. BALANCE. getValue())) {
// // 这笔支付订单原来是充值余额的,退款成功了,需要扣掉会员的本金金额
// UpdateMemberBalanceDTO dto = new UpdateMemberBalanceDTO() ;
// dto. setMemberId( memberId) ;
// dto. setUpdatePrincipalBalance( refundAmount); // 更新会员本金金额,单位元
// dto. setType( MemberWalletEnum. TYPE_OUT. getValue()) ;
// dto. setSubType( MemberWalletEnum. SUBTYPE_USER_REFUND. getValue()) ;
// memberBasicInfoService. updateMemberBalance(dto) ;
// }
//
// // 保存微信退款回调信息
// WxpayRefundCallback record = WxpayRefundCallback. builder( )
// . memberId( memberId)
// . orderCode( orderCode)
// . outTradeNo( out_trade_no)
// . outRefundNo( out_refund_no)
// . transactionId( transaction_id)
// .mchId( refundNotifyResource. getMchid() )
// . refundId( refund_id)
// . refundStatus( refundNotifyResource. getRefund_status() )
// . successTime( refundNotifyResource. getSuccess_time() )
// . userReceivedAccount( refundNotifyResource. getUser_received_account() )
// . payerTotal( refundNotifyResource. getAmount(). getPayer_total() + "" )
// . payerRefund( payer_refund + "") // 微信支付接收单位分
// . amountTotal( refundNotifyResource. getAmount().getTotal() + "" )
// . amountRefund( refundNotifyResource. getAmount().getRefund() + "" )
// .build() ;
// wxpayRefundCallbackService. insertSelective( record) ;
//
// // 记录会员交易流水
// MemberTransactionRecord memberTransactionRecord = MemberTransactionRecord. builder( )
// . orderCode( orderCode)
// . scenarioType( wxpayCallbackRecord. getPayScenario() )
// . memberId( memberId)
// . actionType( ActionTypeEnum. REVERSE. getValue() )
// . payMode( PayModeEnum. PAYMENT_OF_WECHATPAY. getValue() )
// . paymentInstitutions( PaymentInstitutionsEnum. WECHAT_PAY. getValue() )
// . amount( refundAmount) // 记录会员交易流水,单位元
// . outTradeNo( out_trade_no)
// . transactionId( transaction_id)
// . outRefundNo( out_refund_no)
// . refundId( refund_id)
// .build() ;
// memberTransactionRecordService. insertSelective( memberTransactionRecord) ;
// return null;
// }
/**
* 微信支付 申请退款接口
*/
@Override
public WechatPayRefundResponse ApplyForWechatPayRefundV3( WechatPayRefundRequest request) throws JsonProcessingException {
ObjectMapper objectMapper = new ObjectMapper( ) ;
String body = objectMapper. writeValueAsString( request) ;
log . info ( " 申请退款的相关参数是:{} " , body ) ;
Map < String , Object > stringObjectMap = HttpUtils. doPostWexin( WeChatPayParameter. refundJsUrl, body ) ;
log . info ( " 申请退款的返回参数是:{}" , stringObjectMap) ;
return JSON . parseObject ( JSON . toJSONString( stringObjectMap) , WechatPayRefundResponse. class ) ;
}
// @Override
// public WechatPayRefundResponse ApplyForWechatPayRefundV3( WechatPayRefundRequest request) throws JsonProcessingException {
// ObjectMapper objectMapper = new ObjectMapper() ;
// String body = objectMapper. writeValueAsString( request) ;
// log.info("申请退款的相关参数是:{}", body) ;
// Map<String, Object> stringObjectMap = HttpUtils. doPostWexin( WeChatPayParameter. refundJsUrl, body) ;
// log.info(" 申请退款的返回参数是:{}", stringObjectMap) ;
// return JSON.parseObject(JSON. toJSONString( stringObjectMap), WechatPayRefundResponse.class) ;
// }
}