mirror of
https://gitee.com/egzosn/pay-java-parent.git
synced 2026-06-06 00:20:00 +08:00
接通百度支付
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user