客户端的签名代码用的是客户端jar包,服务器端用的服务器jar包,且服务器根本没有签名示例代码。
为此楼主只有强行将客户端部分代码照搬至服务器端,不管是否规范,至少签名在服务器这边处理是做到了。代码如下(代码真心多,但是为了一个类完成所有功能,只能勉强放一起了。):
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.domain.AlipayTradePrecreateModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.*;
import com.alipay.api.response.*;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.Security;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
public class AliPayUtils {
private static final String APP_ID = "";//这个就不强调了,这个都找不到相比开发难度很大,我这文笔很难帮到你了。
private static final String PID = "";//在开放平台内点击右上角那里点击密钥管理,然后点击左边mapi网关产品密钥就能看到pid了。
private static final String APP_PRIVATE_KEY = "";//下面的这些信息在应用信息里边基本能看到,有些可能需要上传设置。
private static final String RSA2_PRIVATE = "";//rsa2私钥
private static final String ALIPAY_PUBLIC_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAnzG+wSFicJ1BAP+/51vY8Zn4ZVNMgWuJCTAvfUh48QjixfJwYdr0lX8aOOHVLiC4zOBMdKi0Ale/R/myl1duCnWhCz9XgxMG/x5MpuxESU0SY6HZimW wQGxoRmKsM3ICa7zmBa58nOig0cKY1ipJ6VXmTGSeiwF7TReKAGU8PeyYTZvnTgmIKofD7L8oAQF2xom3RlFbtzkjf4UaYbr+7m52dktPp6t7PwVKbbAiqDfVIoswrBaAPDmBWrf1Uaj8kt3KVzsiJzpN1xT0oRFikKj9KuMbIMI+ESpDr1674ToJa46AjI+0O8WxfQrebMuE/ xkUCG0WaQCXllLjtRXc7wIDAQAB";
private static final String CHARSET = "UTF-8";
public static boolean alipayCallBack(Map requestParams) {
Boolean isPay = false;
// 获取支付宝POST过来反馈信息
Map params = new HashMap<>();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext(); ) {
String name = (String) iter.next();
String[] values = requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
}
params.put(name, valueStr);
}
try {
boolean flag = AlipaySignature.rsaCheckV1(params, ALIPAY_PUBLIC_KEY, CHARSET, "RSA2");
if (flag) {
String tradeStatus = params.get("trade_status");
if ("TRADE_SUCCESS".equals(tradeStatus)
|| "TRADE_FINISHED".equals(tradeStatus)) {
String outTradeNo = params.get("out_trade_no");// 商户订单号
String tradeNo = params.get("trade_no");// 商户订单号
String gmtPayment = params.get("gmt_payment");// 支付时间
String gmtCreate = params.get("gmt_create");// 创建时间
}
}
} catch (AlipayApiException e) {
e.printStackTrace();
}
return false;
}
public static AlipayTradeQueryResponse getPayInfo(String outTradeNo, String tradeNo) {
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do"
, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
request.setBizContent("{" +
"\"out_trade_no\":\"" + outTradeNo + "\"," +
"\"trade_no\":\"" + tradeNo + "\"," +
"\"org_pid\":\"" + PID + "\"" +
" }");
try {
return alipayClient.execute(request);
} catch (AlipayApiException e) {
return null;
}
}
public static String getPayStr(String totalAmount, String subject, String outTradeNo) {
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do"
, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, "RSA2");
AlipayTradeAppPayRequest request = new AlipayTradeAppPayRequest();
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setSubject(subject);
model.setOutTradeNo(outTradeNo);
model.setTimeoutExpress("10m");
model.setTotalAmount(totalAmount);
model.setProductCode("QUICK_MSECURITY_PAY");
request.setBizModel(model);
request.setNotifyUrl("");//这里记得放支付回调地址
try {
AlipayTradeAppPayResponse response = alipayClient.sdkExecute(request);
if (response.isSuccess()) {
return response.getBody();
} else {
throw new BaseException(BaseResultEnum.ALIPAY_SIGN_ERROR);
}
} catch (AlipayApiException e) {
throw new BaseException(BaseResultEnum.ALIPAY_SIGN_ERROR);
}
}
public static AlipayUserInfoShareResponse signAuthStr(String authCode) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do", APP_ID
, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY
, "RSA2");
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode(authCode);
AlipayUserInfoShareRequest userInfoRequest = new AlipayUserInfoShareRequest();
AlipaySystemOauthTokenResponse response =
alipayClient.execute(request);
if (response.isSuccess()) {
AlipayUserInfoShareResponse userInfoResponse
= alipayClient.execute(userInfoRequest, response.getAccessToken());
if (userInfoResponse.isSuccess()) {
return userInfoResponse;
}
System.out.println("signAuthStr调用成功");
} else {
System.out.println("signAuthStr 调用失败");
}
return null;
}
public static String getAuthStr() {
Map authInfoMap = buildAuthInfoMap();
String info = buildOrderParam(authInfoMap);
String sign = getSign(authInfoMap, RSA2_PRIVATE, true);
return info + "&" + sign;
}
private static String buildOrderParam(Map map) {
List keys = new ArrayList(map.keySet());
StringBuilder sb = new StringBuilder();
for (int i = 0; i < keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
sb.append(buildKeyValue(key, value, true));
sb.append("&");
}
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
sb.append(buildKeyValue(tailKey, tailValue, true));
return sb.toString();
}
private static Map buildAuthInfoMap() {
Map keyValues = new HashMap();
keyValues.put("app_id", APP_ID);
keyValues.put("pid", PID);
keyValues.put("apiname", "com.alipay.account.auth");
keyValues.put("app_name", "mc");
keyValues.put("biz_type", "openservice");
keyValues.put("product_id", "APP_FAST_LOGIN");
keyValues.put("scope", "kuaijie");
keyValues.put("target_id", String.valueOf(System.currentTimeMillis())
+ new Random().nextInt(10000));
keyValues.put("auth_type", "AUTHACCOUNT");
keyValues.put("sign_type", "RSA2");
return keyValues;
}
private static String getSign(Map map, String rsaKey
, boolean rsa2) {
List keys = new ArrayList(map.keySet());
Collections.sort(keys);
StringBuilder authInfo = new StringBuilder();
for (int i = 0; i < keys.size() - 1; i++) {
String key = keys.get(i);
String value = map.get(key);
authInfo.append(buildKeyValue(key, value, false));
authInfo.append("&");
}
String tailKey = keys.get(keys.size() - 1);
String tailValue = map.get(tailKey);
authInfo.append(buildKeyValue(tailKey, tailValue, false));
String oriSign = sign(authInfo.toString(), rsaKey, rsa2);
String encodedSign = "";
try {
encodedSign = URLEncoder.encode(oriSign, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "sign=" + encodedSign;
}
private static String buildKeyValue(String key, String value, boolean isEncode) {
StringBuilder sb = new StringBuilder();
sb.append(key);
sb.append("=");
if (isEncode) {
try {
sb.append(URLEncoder.encode(value, "UTF-8"));
} catch (UnsupportedEncodingException e) {
sb.append(value);
}
} else {
sb.append(value);
}
return sb.toString();
}
private static final String ALGORITHM = "RSA";
private static final String SIGN_ALGORITHMS = "SHA1WithRSA";
private static final String SIGN_SHA256RSA_ALGORITHMS = "SHA256WithRSA";
private static final String DEFAULT_CHARSET = "UTF-8";
private static String getAlgorithms(boolean rsa2) {
return rsa2 ? SIGN_SHA256RSA_ALGORITHMS : SIGN_ALGORITHMS;
}
private static String sign(String content, String privateKey, boolean rsa2) {
try {
PKCS8EncodedKeySpec priPKCS8 = new PKCS8EncodedKeySpec(
Base64.getDecoder().decode(privateKey));
Security.addProvider(
new org.bouncycastle.jce.provider.BouncyCastleProvider());
KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM, "BC");
PrivateKey priKey = keyFactory.generatePrivate(priPKCS8);
java.security.Signature signature = java.security.Signature
.getInstance(getAlgorithms(rsa2));
signature.initSign(priKey);
signature.update(content.getBytes(DEFAULT_CHARSET));
byte[] signed = signature.sign();
return Base64.getEncoder().encodeToString(signed);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
贴完代码可能会有人代码报错,很正常,因为里边用到了官方没有说的代码(原始代码用的Android的jdk没问题,但是服务器端的部分jdk代码和客户端有差异,所以就报错了),解决方案:
# gradle用户在build.gardle加入:
"org.bouncycastle:bcprov-jdk16:1.45",
# mvn用户在pom.xml加入:
org.bouncycastle
bcprov-jdk16
1.45
这样服务器端签名代码就写好(只是签名字符串),调用getAuthStr()方法就能返回了。
首先将获得的realResult上传至服务器。然后我这边贴下服务器端的处理代码(首先是getAlipayAuthCode()方法,传入的是realResult,返回的是authCode,让后将获得的authCode传入signAuthStr()方法就获得了用户信息了,具体的信息可以参考官方文档):
private final String ALIPAY_AUTH_CODE_START = "auth_code=";
private final String ALIPAY_AUTH_CODE_END = "&";
private String getAlipayAuthCode(String response) {
String result = response.substring(response.indexOf(ALIPAY_AUTH_CODE_START)
+ ALIPAY_AUTH_CODE_START.length(), response.length() - 1);
return result.substring(0, result.indexOf(ALIPAY_AUTH_CODE_END));
}
public static AlipayUserInfoShareResponse signAuthStr(String authCode) throws AlipayApiException {
AlipayClient alipayClient = new DefaultAlipayClient(
"https://openapi.alipay.com/gateway.do", APP_ID
, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY
, "RSA2");
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode(authCode);
AlipayUserInfoShareRequest userInfoRequest = new AlipayUserInfoShareRequest();
AlipaySystemOauthTokenResponse response =
alipayClient.execute(request);
if (response.isSuccess()) {
AlipayUserInfoShareResponse userInfoResponse
= alipayClient.execute(userInfoRequest, response.getAccessToken());
if (userInfoResponse.isSuccess()) {
return userInfoResponse;
}
System.out.println("signAuthStr调用成功");
} else {
System.out.println("signAuthStr 调用失败");
}
return null;
}
获得了支付宝用户信息整个登录流程也基本结束了,剩下的就是自己业务逻辑的处理了,因为整个流程实在太复杂,写的可能有很多不详细的地方,还望谅解,发现不对的地方还望及时指正,有问题也可以评论指出。