服务商获取证书参数配置
import com.cieo.util.PropertyUtil;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.Verifier;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Validator;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URIBuilder;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Component;
import java.nio.charset.StandardCharsets;
import java.security.PrivateKey;
import static org.apache.http.HttpHeaders.ACCEPT;
import static org.apache.http.entity.ContentType.APPLICATION_JSON;
/**
* 服务商支付参数
* @author terry
*/
@Component
@Slf4j
@RefreshScope
@Data
public class WeChatServicePayV3Config {
/**
* 商户证书序列号
*/
private String merchantSerialNumber = "商户证书序列号";
/**
* 私钥 apiclient_key.pem文件的值
*/
private String privateKey = "-----BEGIN PRIVATE KEY-----\n" +
"MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCyEvVWy/vQ2z01\n" +
"iJgULoMyEVbPFetVMPcC5lhlg1ZN/3oYE/TJI8fMWkm/CUsmqf/I541aYDDZ9oaH\n" +
"ol3Sp9n2g8lvIR2tM8rr7nc+PkQ2rnILOELivndUzE9BTj9E63fD8QTTKMWPgiJB\n" +
"gBXiVX4TR7DiBqVUi0l8/fbY\n" +
"-----END PRIVATE KEY-----";
private static final HttpHost proxy = null;
/**
* 平台证书认证
*/
private Verifier verifier;
/**
* 创建平台证书验证
*
* @return 平台证书验证对象
* @throws Exception
*/
public Verifier createVerifier() throws Exception {
String merchantId = PropertyUtil.getProperty("charge.service.wechat.miniapp.mchId");
String apiV3Key = PropertyUtil.getProperty("charge.service.wechat.miniapp.v3.key");
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(privateKey);
// 获取证书管理器实例
CertificatesManager certificatesManager = CertificatesManager.getInstance();
// 添加代理服务器
certificatesManager.setProxy(proxy);
// 向证书管理器增加需要自动更新平台证书的商户信息
certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,
new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)),
apiV3Key.getBytes(StandardCharsets.UTF_8));
// 从证书管理器中获取verifier
Verifier verifier = certificatesManager.getVerifier(merchantId);
// 构造httpclient
CloseableHttpClient httpClient = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
.withValidator(new WechatPay2Validator(verifier))
.build();
URIBuilder uriBuilder = new URIBuilder("https://api.mch.weixin.qq.com/v3/certificates");
HttpGet httpGet = new HttpGet(uriBuilder.build());
httpGet.addHeader(ACCEPT, APPLICATION_JSON.toString());
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
HttpEntity entity = response.getEntity();
EntityUtils.consume(entity);
} finally {
response.close();
}
return verifier;
}
}
微信支付证书书定时刷新任务
@Component
@Slf4j
public class WhChatTask {
@Resource
private WeChatServicePayV3Config weChatServicePayV3Config;
/**
* 定时刷新证书
*@throws Exception 抛出异常
*/
@Scheduled(cron = "0 */30 * * * ?")
public void getVerifierRefresh()throws Exception {
weChatServicePayV3Config.setVerifier(weChatServicePayV3Config.createVerifier());
}
/**
*启动加载证书
* @throws Exception
*/
@Scheduled(initialDelay = 1000, fixedRate = Long.MAX_VALUE)
public void test()throws Exception {
weChatServicePayV3Config.setVerifier(weChatServicePayV3Config.createVerifier());
}
}
服务商微信预下单
public Map<String, Object> servicePay( String openCode,String outTradeNo,Integer total,String description,String preOrderId) throws Exception {
WeChatCode2SessionDo authorization_code = weChatAuthClient.jsCode2Session(PropertyUtil.getProperty("charge.wechat.miniapp.appId"),
PropertyUtil.getProperty("charge.wechat.miniapp.secret"),
openCode,
"authorization_code"
);
String privateKey = weChatServicePayV3Config.getPrivateKey();
String merchantSerialNumber = weChatServicePayV3Config.getMerchantSerialNumber();
String merchantId = PropertyUtil.getProperty("charge.service.wechat.miniapp.mchId");
String cisMerchantId = PropertyUtil.getProperty("charge.service.wechat.miniapp.cis.mchId");
String appId = PropertyUtil.getProperty("charge.wechat.miniapp.appId");
String callbackUrl = PropertyUtil.getProperty("forest.variables.weChatServerCallBackUrlServicePayV3");
PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(privateKey);
X509Certificate wechatPayCertificate = weChatServicePayV3Config.getVerifier().getValidCertificate();
ArrayList<X509Certificate> wechatPayCertificates = new ArrayList<>();
wechatPayCertificates.add(wechatPayCertificate);
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(merchantId, merchantSerialNumber, merchantPrivateKey)
.withWechatPay(wechatPayCertificates);
CloseableHttpClient httpClient = builder.build();
HttpPost httpPost = new HttpPost("https://api.mch.weixin.qq.com/v3/pay/partner/transactions/jsapi");
httpPost.addHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode rootNode = objectMapper.createObjectNode();
rootNode.put("sp_mchid", merchantId)
.put("sp_appid", appId)
.put("sub_mchid", cisMerchantId)
.put("description", description)
.put("notify_url", callbackUrl)
.put("out_trade_no", outTradeNo);
rootNode.putObject("amount")
.put("total", total);
rootNode.putObject("payer")
.put("sp_openid", authorization_code.getOpenid());
objectMapper.writeValue(bos, rootNode);
httpPost.setEntity(new StringEntity(bos.toString("UTF-8"), "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
String bodyAsString = EntityUtils.toString(response.getEntity());
System.out.println("支付回参:+"+bodyAsString);
String prepayId = JSONObject.parseObject(bodyAsString).getString("prepay_id");
if(StringUtil.isBlank(prepayId)){
PreOrderEvent.PreOrderDeleteHandel excelHandel = new PreOrderEvent.PreOrderDeleteHandel(preOrderId);
eventManager.eventPublish(excelHandel, KelpConstants.adminId);
Magic.throwException("下订单失败:"+bodyAsString);
}
String packageStr = "prepay_id=" + prepayId;
JSONObject payMap = new JSONObject();
payMap.put("appId", appId);
long timestamp = System.currentTimeMillis() / 1000;
payMap.put("timeStamp", timestamp + "");
String nonceStr = WeChatPayV3Util.getRandomStringByLength(32);
payMap.put("nonceStr", nonceStr);
payMap.put("package", packageStr);
payMap.put("signType", "RSA");
// 生成请求签名
String packageSign = WeChatPayV3Util.sign(WeChatPayV3Util.buildMessage(appId, timestamp, nonceStr, packageStr).getBytes(), privateKey);
payMap.put("paySign", packageSign);
bos.close();
httpClient.close();
return payMap;
}
小程序paySign参数的加密
public static String sign(byte[] message, String privateKey) throws SignatureException,InvalidKeyException, NoSuchAlgorithmException {
//签名方式
Signature sign = Signature.getInstance("SHA256withRSA");
//私钥
sign.initSign(PemUtil.loadPrivateKey(privateKey));
sign.update(message);
return Base64.getEncoder().encodeToString(sign.sign());
}