@Data
@ToString
@NoArgsConstructor
@AllArgsConstructor
public class TransfersVO {
private byte [ ] certData;
private String mchAppid;
private String mchId;
private String mchName;
private String partnerTradeNo;
private String openid;
private String checkName = "NO_CHECK" ;
private Double amount;
private String nonceStr;
private String desc;
private String appKey;
private String sceneId;
private String spbillCreateIp = "127.0.0.1" ;
@Transient
public Map < String , String > map ( )
{
Map < String , String > map = new HashMap < String , String > ( ) ;
map. put ( "mch_appid" , this . mchAppid) ;
map. put ( "mchid" , this . mchId) ;
map. put ( "mch_name" , this . mchName) ;
map. put ( "openid" , this . openid) ;
map. put ( "amount" , String . valueOf ( this . amount) ) ;
map. put ( "desc" , this . desc) ;
map. put ( "appkey" , this . appKey) ;
map. put ( "nonce_str" , this . nonceStr) ;
map. put ( "partner_trade_no" , this . partnerTradeNo) ;
map. put ( "spbill_create_ip" , this . spbillCreateIp) ;
return map;
}
public InputStream getCertStream ( String certPath) throws IOException {
File file = new File ( certPath) ;
InputStream certStream = new FileInputStream ( file) ;
this . certData = new byte [ ( int ) file. length ( ) ] ;
certStream. read ( this . certData) ;
certStream. close ( ) ;
ByteArrayInputStream certBis = new ByteArrayInputStream ( this . certData) ;
return certBis;
}
}
@Component
@Slf4j
public class WxUtils {
public static void doTransfers ( String mchKey, String certPath, TransfersVO model) {
try {
String paramStr = WxUtils . createLinkString ( model, mchKey) ;
String sign = DigestUtils . md5Hex ( paramStr) . toUpperCase ( ) ;
StringBuilder reqXmlStr = new StringBuilder ( ) ;
reqXmlStr. append ( "<xml>" ) ;
reqXmlStr. append ( "<mchid>" + model. getMchId ( ) + "</mchid>" ) ;
reqXmlStr. append ( "<mch_appid>" + model. getMchAppid ( ) + "</mch_appid>" ) ;
reqXmlStr. append ( "<nonce_str>" + model. getNonceStr ( ) + "</nonce_str>" ) ;
reqXmlStr. append ( "<check_name>" + model. getCheckName ( ) + "</check_name>" ) ;
reqXmlStr. append ( "<openid>" + model. getOpenid ( ) + "</openid>" ) ;
reqXmlStr. append ( "<amount>" + model. getAmount ( ) . intValue ( ) + "</amount>" ) ;
reqXmlStr. append ( "<desc>" + model. getDesc ( ) + "</desc>" ) ;
reqXmlStr. append ( "<sign>" + sign + "</sign>" ) ;
reqXmlStr. append ( "<partner_trade_no>" + model. getPartnerTradeNo ( ) + "</partner_trade_no>" ) ;
reqXmlStr. append ( "</xml>" ) ;
String result = WxPayRequestUtils . httpsRequest ( TRANS_URL, reqXmlStr. toString ( ) ,
model, certPath) ;
if ( result. contains ( "CDATA[FAIL]" ) ) {
log. info ( "领取红包结果:" + result) ;
throw new ServiceException ( ResultCodeEnum . BUSINESS_ERROR. getCode ( ) , "领取红包失败" ) ;
} else {
}
} catch ( Exception e) {
log. error ( "领取红包出现异常:{}" , e) ;
}
}
private static String createLinkString ( TransfersVO model, String mchKey) {
Map < String , Object > paramMap = new HashMap < String , Object > ( ) ;
paramMap. put ( "mch_appid" , model. getMchAppid ( ) ) ;
paramMap. put ( "mchid" , model. getMchId ( ) ) ;
paramMap. put ( "openid" , model. getOpenid ( ) ) ;
paramMap. put ( "amount" , model. getAmount ( ) . intValue ( ) ) ;
paramMap. put ( "check_name" , model. getCheckName ( ) ) ;
paramMap. put ( "desc" , model. getDesc ( ) ) ;
paramMap. put ( "partner_trade_no" , model. getPartnerTradeNo ( ) ) ;
paramMap. put ( "nonce_str" , model. getNonceStr ( ) ) ;
List < String > keys = new ArrayList ( paramMap. keySet ( ) ) ;
Collections . sort ( keys) ;
StringBuilder preStr = new StringBuilder ( ) ;
for ( int i = 0 ; i < keys. size ( ) ; i++ ) {
String key = keys. get ( i) ;
Object value = paramMap. get ( key) ;
if ( i == keys. size ( ) - 1 ) {
preStr. append ( key) . append ( "=" ) . append ( value) ;
} else {
preStr. append ( key) . append ( "=" ) . append ( value) . append ( "&" ) ;
}
}
preStr. append ( "&key=" + mchKey) ;
return preStr. toString ( ) ;
}
}
@Component
public class WxPayRequestUtils {
private int socketTimeout = 10000 ;
private int connectTimeout = 30000 ;
private static RequestConfig requestConfig;
private static CloseableHttpClient httpClient;
private static void initCert ( String path, TransfersVO transfer) throws Exception {
BasicHttpClientConnectionManager connManager;
char [ ] password = transfer. getMchId ( ) . toCharArray ( ) ;
InputStream certStream = transfer. getCertStream ( path) ;
KeyStore ks = KeyStore . getInstance ( "PKCS12" ) ;
ks. load ( certStream, password) ;
KeyManagerFactory kmf = KeyManagerFactory . getInstance ( KeyManagerFactory . getDefaultAlgorithm ( ) ) ;
kmf. init ( ks, password) ;
SSLContext sslContext = SSLContext . getInstance ( "TLS" ) ;
sslContext. init ( kmf. getKeyManagers ( ) , null , new SecureRandom ( ) ) ;
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory (
sslContext,
new DefaultHostnameVerifier ( ) ) ;
connManager = new BasicHttpClientConnectionManager (
RegistryBuilder . < ConnectionSocketFactory > create ( )
. register ( "http" , PlainConnectionSocketFactory . getSocketFactory ( ) )
. register ( "https" , sslConnectionSocketFactory)
. build ( ) ,
null ,
null ,
null
) ;
httpClient = HttpClientBuilder . create ( )
. setConnectionManager ( connManager)
. build ( ) ;
}
public static String httpsRequest ( String url, String xmlObj, TransfersVO model, String path) throws Exception {
initCert ( path, model) ;
String result = null ;
HttpPost httpPost = new HttpPost ( url) ;
StringEntity postEntity = new StringEntity ( xmlObj, "UTF-8" ) ;
httpPost. addHeader ( "Content-Type" , "text/xml" ) ;
httpPost. setEntity ( postEntity) ;
HttpResponse response = httpClient. execute ( httpPost) ;
HttpEntity entity = response. getEntity ( ) ;
result = EntityUtils . toString ( entity, "UTF-8" ) ;
httpPost. abort ( ) ;
return result;
}
}
@Test
public void testReward ( ) throws Exception {
TransfersVO model = new TransfersVO ( ) ;
model. setMchId ( "" ) ;
model. setMchAppid ( "" ) ;
model. setMchName ( "" ) ;
model. setOpenid ( "" ) ;
model. setAmount ( 40.0 ) ;
model. setDesc ( "红包" ) ;
model. setSceneId ( "PRODUCT_4" ) ;
String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ;
Random random = new Random ( ) ;
StringBuilder sb = new StringBuilder ( ) ;
for ( int i = 0 ; i < 15 ; i++ ) {
int number = random. nextInt ( base. length ( ) ) ;
sb. append ( base. charAt ( number) ) ;
}
model. setNonceStr ( sb. toString ( ) ) ;
String partnerTradeNo = model. getMchId ( )
+ new SimpleDateFormat ( "yyyyMMddHHmmss" ) . format ( new Date ( ) )
+ ( int ) ( ( Math . random ( ) * 9 + 1 ) * 1000 ) ;
model. setPartnerTradeNo ( partnerTradeNo) ;
WxUtils . doTransfers ( "商户密钥" , "证书路径" , model) ;
}