springboot集成⽀付APIv3接⼝实现⼩程序和⽀付前⾔:
⽹上有很多⼤佬们集成的综合⽀付包,做相应配置也很⽅便,我这个是基于官⽅⽂档流程做的直连模式,实现和⼩程序⽀付(需要代码中正确使⽤appid),不得不吐槽的⽂档还是⼀如既往的。。。
1.引⼊maven依赖
<dependency>
<groupId>com.github.wechatpay-apiv3</groupId>
<artifactId>wechatpay-apache-httpclient</artifactId>
<version>0.3.0</version>
</dependency>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.5</version>
</dependency>
2.yaml配置
wx:
pay:
mchId: 16126xxxx #⽀付商户号
mchSerialNo: 60B04XXXXXXXXX #证书序列号
v3Secret: 5ovxxxxxxxxxxxxxxxx #密钥
p12Path:/usr/local/apiclient_cert.p12 #证书绝对路径地址
keyPass:16126xxxx #证书密码默认商户号
privateKey: | #这个符号⼀定注意(回车键旁边) 是yaml中保持⽂本换⾏读取的写法防⽌证书读出来加载失败
-----BEGIN PRIVATE KEY-----
xxxx
-----END PRIVATE KEY----- #私钥
certificate: |
-----BEGIN CERTIFICATE-----
xxxx
-----END CERTIFICATE----- #平台证书
特别提⽰:
3.读取yaml内容的Properties类
@Data
@Componentspring怎么读取properties
@ConfigurationProperties(prefix = "wx.pay")
public class WeChatPayProperties {
/**
* 商户id
*/
private String mchId;
/**
* 商户证书序列号
*/
private String mchSerialNo;
/
**
* apiV3密钥
*/
private String v3Secret;
/**
* p12证书⽂件位置
*/
private String p12Path;
/**
* 证书密码
*/
private String keyPass;
/**
* 商户私钥
*/
private String privateKey;
/**
* ⽀付平台证书 jar包⽣产的
*/
private String certificate;
}
4.启动配置类
@Configuration
public class WxPayV3Config {
@Autowired
WeChatPayProperties weChatPayProperties;
@Bean
public CloseableHttpClient wxV3Init() {
PrivateKey merchantPrivateKey = PemUtil.PrivateKey());
X509Certificate wechatPayCertificate = PemUtil.loadCertificate(
new Certificate().getBytes(StandardCharsets.UTF_8)));
ArrayList<X509Certificate> listCertificates = new ArrayList<>();
listCertificates.add(wechatPayCertificate);
ate()
.MchId(), MchSerialNo(), merchantPrivateKey)
.withWechatPay(listCertificates)
.build();
}
}
5.下单api
@Slf4j
@Component
public class WeChatPayApi {
@Autowired
WeChatPayProperties weChatPayProperties;
@Autowired
WeChatAppletProperties weChatAppletProperties;
@Autowired
CloseableHttpClient httpClient;
/**
* ⼩程序下单的请求地址
*/
private static final String applet_req_url = "h.weixin.qq/v3/pay/transactions/jsapi";/**
* 创建⼩程序订单
*
* @param orderNo 订单号
* @param amount 单位分
* @param openid ⼩程序的openid
* @param goodsName 订单名称
* @param notify 通知地址
* @throws IOException
*/
public String createWxAppletOrder(String orderNo, Integer amount, String openid, String goodsName, String notify) throws IOException {// 请求body参数 JSONObject paramObject = new JSONObject();
JSONObject amountObject = new JSONObject();
amountObject.put("total", amount);
amountObject.put("currency", "CNY");
paramObject.put("amount", amountObject);
paramObject.put("mchid", MchId());
paramObject.put("description", goodsName);
paramObject.put("notify_url", notify);
JSONObject payerObject = new JSONObject();
payerObject.put("openid", openid);
paramObject.put("payer", payerObject);
paramObject.put("out_trade_no", orderNo);
paramObject.put("appid", "⼩程序appid");
HttpPost httpPost = new HttpPost(applet_req_url);
httpPost.setHeader("Accept", "application/json");
StringEntity entity = new JSONString(), "utf-8");
entity.setContentType("application/json");
log.info("[下单请求参数列表]=" + paramObject);
httpPost.setEntity(entity);
//完成签名并执⾏请求
CloseableHttpResponse response = ute(httpPost);
Map<String, Object> resMap = new HashMap<>();
try {
int statusCode = StatusLine().getStatusCode();
Assert.isTrue(statusCode == 200, "下单请求失败");
JSONObject jsonObject = JSON.Entity()));
String prepayId = String("prepay_id");
Assert.isTrue(StringUtils.isNotBlank(prepayId), "下单获取参数失败");
String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonceStr = RandomUtil.randomString(32).toUpperCase();
String packagep = "prepay_id=" + prepayId;
SortedMap<Object, Object> params = new TreeMap<>();
params.put("appId", AppId());
params.put("timeStamp", timeStamp);
params.put("nonceStr", nonceStr);
params.put("package", packagep);
params.put("signType", "RSA");
resMap.put("appId", "⼩程序appid");
resMap.put("timeStamp", timeStamp);
resMap.put("nonceStr", nonceStr);
resMap.put("package", packagep);
resMap.put("signType", "RSA");
resMap.put("paySign", ateSign(params, P12Path(), KeyPass())); log.info("[⽀付] ⽀付参数:" + JSONString(resMap));
} catch (Exception e) {
throw new Message());
} finally {
response.close();
}
JSONString(resMap);
}
6.paySign签名⽣成 WechatPayUtils类,KeyPairFactory类,WechatRSAUtils类
public class WechatPayUtils {
/**
* sign签名
*
* @param map
* @return
*/
public static String createSign(SortedMap<Object, Object> map, String certPath, String keyPass) throws Exception {
String signatureStr = Stream.of(
String.("appId"))
, String.("timeStamp"))
, String.("nonceStr"))
, String.("package"))
).collect(Collectors.joining("\n", "", "\n"));
KeyPair keyPair = atePKCS12(certPath, "Tenpay Certificate", keyPass);
return WechatRSAUtils.payRequestSign(signatureStr, keyPair);
}
public class KeyPairFactory {
private static KeyStore store;
private static final Object lock = new Object();
/**
* 获取公私钥.
*
* @param keyPath the key path
* @param keyAlias the key alias
* @param keyPass password
* @return the key pair
*/
public static KeyPair createPKCS12(String keyPath, String keyAlias, String keyPass) throws Exception {
// ClassPathResource resource = new ClassPathResource(keyPath); //喜欢⽤相对路径的同学使⽤这⼀⾏
PathResource resource = new PathResource(keyPath);
char[] pem = CharArray();
synchronized (lock) {
if (store == null) {
synchronized (lock) {
store = Instance("PKCS12");
store.InputStream(), pem);
}
}
}
X509Certificate certificate = (X509Certificate) Certificate(keyAlias);
certificate.checkValidity();
// 证书的序列号也有⽤
String serialNumber = SerialNumber().toString(16).toUpperCase();
// 证书的公钥
PublicKey publicKey = PublicKey();
// 证书的私钥
PrivateKey storeKey = (PrivateKey) Key(keyAlias, pem);
return new KeyPair(publicKey, storeKey);
}
}
public class WechatRSAUtils {
/**
* ⽣成⽀付签名
*
* @param signStr
* @param keyPair
* @return
**/
@SneakyThrows
public static String payRequestSign(String signStr, KeyPair keyPair) {
Signature sign = Instance("SHA256withRSA");
sign.Private());
sign.Bytes(StandardCharsets.UTF_8));
deToString(sign.sign());
}
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论