接通百度支付

This commit is contained in:
Menjoe
2021-04-12 22:04:20 +08:00
parent 74155a4713
commit 66a9966e6c
3 changed files with 149 additions and 30 deletions

View File

@@ -3,13 +3,23 @@ package com.egzosn.pay.baidu.api;
import com.egzosn.pay.common.api.BasePayConfigStorage;
public class BaiduPayConfigStorage extends BasePayConfigStorage {
private String appId;
private String appid;
private String dealId;
/**
* 支付平台公钥(签名校验使用)
*/
private String keyPublic;
@Override
@Deprecated
public String getAppid() {
return this.appId;
return this.appid;
}
@Override
public String getAppId() {
return this.appid;
}
@Override
@@ -17,9 +27,10 @@ public class BaiduPayConfigStorage extends BasePayConfigStorage {
return getDealId();
}
//使用json序列化的时候会报错所以不要直接抛出异常
@Override
public String getSeller() {
throw new UnsupportedOperationException("不支持");
return getDealId();
}
public String getDealId() {
@@ -31,33 +42,25 @@ public class BaiduPayConfigStorage extends BasePayConfigStorage {
}
public String getAppKey() {
return this.getKeyPrivate();
return this.appid;
}
public void setAppKey(String appKey) {
setKeyPrivate(appKey);
this.setAppid(appKey);
}
@Override
public String getKeyPublic() {
return super.getKeyPrivate();
return keyPublic;
}
@Override
public void setKeyPublic(String keyPublic) {
super.setKeyPublic(keyPublic);
this.keyPublic = keyPublic;
}
public void setAppid(String appId) {
this.appId = appId;
public void setAppid(String appid) {
this.appid = appid;
}
@Override
public String getAppId() {
return appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
}

View File

@@ -1,9 +1,13 @@
package com.egzosn.pay.baidu.api;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.net.URLEncoder;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
@@ -51,6 +55,13 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
public static final String RESPONSE_STATUS = "status";
private static final String CHARSET = "UTF-8";
private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String SIGN_TYPE_RSA = "RSA";
private static final String SIGN_KEY = "rsaSign";
public static final String PAY_MONEY = "payMoney";
public BaiduPayService(BaiduPayConfigStorage payConfigStorage) {
super(payConfigStorage);
}
@@ -68,12 +79,103 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
*/
@Override
public boolean verify(Map<String, Object> params) {
if (!RESPONSE_SUCCESS.equals(params.get(RESPONSE_STATUS))) {
if (!RESPONSE_SUCCESS.equals(params.get(RESPONSE_STATUS)) && !RESPONSE_SUCCESS.toString().equals(params.get(RESPONSE_STATUS))) {
return false;
}
return signVerify(params, String.valueOf(params.get(RSA_SIGN)));
LOG.info("开始验证回调签名参数:" + params);
try {
boolean checkSign = this.checkReturnSign(params, payConfigStorage.getKeyPublic(), (String) params.get(RSA_SIGN));
return checkSign;
} catch (Exception e) {
LOG.info("验签失败", e);
}
return false;
}
public boolean checkReturnSign(Map<String, Object> params, String publicKey, String rsaSign) {
try {
String content = signContent(params);
Signature signature = Signature.getInstance(SIGN_ALGORITHMS);
signature.initVerify(this.getPublicKeyX509(publicKey));
signature.update(content.getBytes(CHARSET));
boolean verify = signature.verify(Base64.getDecoder().decode(rsaSign.getBytes(CHARSET)));
LOG.info("使用公钥进行验签: " + verify);
return verify;
} catch (Exception e) {
LOG.info("使用公钥进行验签出错, 返回false", e);
}
return false;
}
/**
* 将公钥字符串进行Base64 decode之后生成X509标准公钥
*
* @param publicKey 公钥原始字符串
*
* @return X509标准公钥
*
* @throws InvalidKeySpecException
* @throws NoSuchAlgorithmException
*/
private static PublicKey getPublicKeyX509(String publicKey) throws InvalidKeySpecException,
NoSuchAlgorithmException, UnsupportedEncodingException {
if (StringUtils.isEmpty(publicKey)) {
return null;
}
KeyFactory keyFactory = KeyFactory.getInstance(SIGN_TYPE_RSA);
byte[] decodedKey = Base64.getDecoder().decode(publicKey.getBytes(CHARSET));
return keyFactory.generatePublic(new X509EncodedKeySpec(decodedKey));
}
/**
* 对输入参数进行key过滤排序和字符串拼接
*
* @param params 待签名参数集合
*
* @return 待签名内容
*
* @throws UnsupportedEncodingException
*/
private String signContent(Map<String, Object> params) throws UnsupportedEncodingException {
Map<String, String> sortedParams = new TreeMap<>(Comparator.naturalOrder());
for (Map.Entry<String, Object> entry : params.entrySet()) {
String key = entry.getKey();
if (legalKey(key)) {
String value =
entry.getValue() == null ? null : URLEncoder.encode(entry.getValue().toString(), CHARSET);
sortedParams.put(key, value);
}
}
StringBuilder builder = new StringBuilder();
if (sortedParams != null && sortedParams.size() > 1) {
for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
if (StringUtils.equals(entry.getKey(), RSA_SIGN)) continue;
builder.append(entry.getKey());
builder.append("=");
builder.append(entry.getValue());
builder.append("&");
}
builder.deleteCharAt(builder.length() - 1);
}
LOG.info("验签字符串:\n" + builder);
return builder.toString();
}
/**
* 有效的待签名参数key值
* 非空、且非签名字段
*
* @param key 待签名参数key值
*
* @return true | false
*/
private static boolean legalKey(String key) {
return StringUtils.isNotBlank(key) && !SIGN_KEY.equalsIgnoreCase(key);
}
/**
* 验证签名
*
@@ -97,8 +199,9 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
*/
@Override
public Map<String, Object> orderInfo(PayOrder order) {
Map<String, Object> params = getUseOrderInfoParams(order);
String rsaSign = getRsaSign(params, RSA_SIGN);
LOG.info("百度支付配置:" + JSON.toJSONString(payConfigStorage));
Map<String, Object> params = this.getUseOrderInfoParams(order);
String rsaSign = this.getRsaSign(params, RSA_SIGN);
params.put(RSA_SIGN, rsaSign);
return params;
}
@@ -128,12 +231,15 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
String appKey = payConfigStorage.getAppKey();
String dealId = payConfigStorage.getDealId();
result.put(APP_KEY, appKey);
result.put(TP_ORDER_ID, payOrder.getTradeNo());
result.put(DEAL_ID, dealId);
result.put(TOTAL_AMOUNT, String.valueOf(Util.conversionCentAmount(order.getPrice())));
result.put(TP_ORDER_ID, payOrder.getOutTradeNo());
result.put(DEAL_TITLE, payOrder.getSubject());
result.put(SIGN_FIELDS_RANGE, payOrder.getSignFieldsRange());
result.put(BIZ_INFO, JSON.toJSONString(payOrder.getBizInfo()));
result.put(TOTAL_AMOUNT, String.valueOf(Util.conversionAmount(order.getPrice())));
LOG.info("百度支付 getUseOrderInfoParams" + JSON.toJSONString(result));
return result;
}
@@ -489,7 +595,17 @@ public class BaiduPayService extends BasePayService<BaiduPayConfigStorage> {
* @return 签名结果
*/
private String getRsaSign(Map<String, Object> params, String... ignoreKeys) {
String waitSignVal = SignUtils.parameterText(params, "&", false, ignoreKeys);
return SignUtils.valueOf(payConfigStorage.getSignType()).createSign(waitSignVal, payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset());
Map<String, Object> result = new HashMap<>();
String appKey = payConfigStorage.getAppKey();
String dealId = payConfigStorage.getDealId();
result.put(APP_KEY, appKey);
result.put(DEAL_ID, dealId);
result.put(TOTAL_AMOUNT, params.get(TOTAL_AMOUNT));
result.put(TP_ORDER_ID, params.get(TP_ORDER_ID));
LOG.info("百度支付签名参数:" + JSON.toJSONString(result));
String waitSignVal = SignUtils.parameterText(result, "&", false, ignoreKeys);
return SignUtils.RSA.createSign(waitSignVal, payConfigStorage.getKeyPrivate(), payConfigStorage.getInputCharset());
}
}

View File

@@ -13,7 +13,7 @@ public class BaiduPayServiceTest {
@Test
public void orderInfo() {
BaiduPayConfigStorage configStorage = new BaiduPayConfigStorage();
configStorage.setAppId("APP ID");
configStorage.setAppid("APP ID");
configStorage.setAppKey("APP KEY");
configStorage.setDealId("DEAL ID");
configStorage.setKeyPublic("KEY PUBLIC");