package com.xinquan.order.utils;
|
|
import cn.hutool.http.HttpRequest;
|
import cn.hutool.http.HttpResponse;
|
import cn.hutool.http.HttpUtil;
|
import com.alibaba.fastjson2.JSON;
|
import com.alibaba.fastjson2.JSONObject;
|
import com.xinquan.common.core.exception.ServiceException;
|
import com.xinquan.common.core.utils.DateUtils;
|
import com.xinquan.common.core.utils.StringUtils;
|
import java.security.KeyFactory;
|
import java.security.PrivateKey;
|
import java.security.Signature;
|
import java.security.spec.PKCS8EncodedKeySpec;
|
import java.util.Base64;
|
import java.util.HashMap;
|
import java.util.Map;
|
import java.util.TreeMap;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
|
/**
|
* 桔禾付支付工具类
|
*
|
* @author mitao
|
* @date 2024/9/7
|
*/
|
public class JuHeFuUtil {
|
|
private static Logger logger = LoggerFactory.getLogger(JuHeFuUtil.class);
|
// 商户RSA私钥 TODO
|
private static final String MERCHANT_PRIVATE_KEY = "";
|
// 平台RSA公钥 TODO
|
private static final String PLAT_PUBLIC_KEY = "";
|
// 应用的app_id TODO
|
private static final String APP_ID = "";
|
// 商户id TODO
|
private static final String MER_ID = "";
|
// AES密钥 TODO
|
private static final String AES_KEY = "";
|
// 创建用户接口
|
private static final String CREATE_USER_INTERFACE = "/api/member/create_user_a";
|
// 创建支付订单
|
private static final String CREATE_PAYMENT_INTERFACE = "/api/payment/create_payment";
|
// 退款接口
|
private static final String PAYMENT_REFUND_INTERFACE = "/api/payment/payment_refund";
|
private static final String MERCHANT_PAY_INTERFACE = "/api/account/merchant_pay";
|
// 接口地址 TODO
|
private static final String BASE_URL = "";
|
// 支付宝支付渠道
|
private static final String PAY_CHANNEL_ALIPAY = "alipay_qr";
|
// 微信支付渠道
|
private static final String PAY_CHANNEL_WECHAT = "wx_lite";
|
// 微信小程序id TODO
|
private static final String WX_APP_ID = "";
|
|
/**
|
* 创建用户
|
*
|
* @param memberId 用户id
|
* @param memberP 用户信息
|
* @return boolean
|
* @throws Exception
|
*/
|
public static boolean createUser(String memberId, Map<String, Object> memberP)
|
throws Exception {
|
JSONObject data = new JSONObject();
|
data.put("app_id", APP_ID);
|
data.put("member_id", memberId);
|
data.put("member_type", "01");
|
data.put("member_p", memberP);
|
|
JSONObject body = new JSONObject();
|
body.put("merId", MER_ID);
|
body.put("sign", sign(JSONObject.toJSONString(data)));
|
body.put("reqCipher",
|
EncryptUtils.aes256ECBPkcs7PaddingEncrypt(JSONObject.toJSONString(data), AES_KEY));
|
body.put("reqTime", DateUtils.dateTimeNow("yyyyMMddHHmmssfff"));
|
// 发送Post请求
|
logger.info("桔禾付创建用户请求体====================>{}", body.toJSONString());
|
String result = sendPost(BASE_URL + CREATE_USER_INTERFACE, body);
|
logger.info("桔禾付创建用户请求结果====================>{}", result);
|
if (StringUtils.isBlank(result)) {
|
throw new ServiceException("请求第三方支付平台异常");
|
}
|
JSONObject resJsonObject = JSONObject.parseObject(result);
|
if (resJsonObject.getString("status").equals("succeeded")) {
|
return true;
|
} else if (resJsonObject.getString("status").equals("failed")) {
|
throw new ServiceException(resJsonObject.getString("error_msg"));
|
}
|
return false;
|
}
|
|
/**
|
* 创建支付订单
|
*
|
* @param orderNo 订单号
|
* @param payChannel 支付渠道 1:支付宝 2:微信
|
* @param payAmt 支付金额
|
* @param goodsTitle 商品标题
|
* @param goodsDesc 商品描述信息,微信小程序和微信公众号该字段 最大长度 42 个字符
|
* @param deviceIp 设备支付公网ip
|
* @param openId 微信openId
|
* @param notifyUrl 回调地址
|
* @return JSONObject
|
* @throws Exception
|
*/
|
public static JSONObject createPayment(String orderNo, Integer payChannel, String payAmt,
|
String goodsTitle, String goodsDesc, String deviceIp, String openId,
|
String notifyUrl) throws Exception {
|
JSONObject data = new JSONObject();
|
JSONObject expand = new JSONObject();
|
data.put("order_no", orderNo);
|
data.put("app_id", APP_ID);
|
data.put("mer_id", MER_ID);
|
if (payChannel == 1) {
|
data.put("pay_channel", PAY_CHANNEL_ALIPAY);
|
} else {
|
data.put("pay_channel", PAY_CHANNEL_WECHAT);
|
expand.put("open_id", openId);
|
expand.put("wx_app_id", WX_APP_ID);
|
data.put("expand", expand);
|
}
|
data.put("pay_amt", payAmt);
|
data.put("goods_title", goodsTitle);
|
data.put("goods_desc", goodsDesc);
|
Map<String, Object> deviceInfo = new HashMap<>();
|
deviceInfo.put("device_ip", deviceIp);
|
data.put("device_info", deviceInfo);
|
data.put("notify_url", notifyUrl);
|
JSONObject body = new JSONObject();
|
body.put("merId", MER_ID);
|
body.put("sign", sign(JSONObject.toJSONString(data)));
|
body.put("reqCipher",
|
EncryptUtils.aes256ECBPkcs7PaddingEncrypt(JSONObject.toJSONString(data), AES_KEY));
|
body.put("reqTime", DateUtils.dateTimeNow("yyyyMMddHHmmssfff"));
|
String result = sendPost(BASE_URL + CREATE_PAYMENT_INTERFACE, body);
|
JSONObject resJsonObject = JSONObject.parseObject(result);
|
if (resJsonObject.getString("status").equals("failed")) {
|
throw new ServiceException(resJsonObject.getString("error_msg"));
|
}
|
if (resJsonObject.getString("status").equals("succeeded")) {
|
return resJsonObject.getJSONObject("expand");
|
}
|
return null;
|
}
|
|
/**
|
* 申请退款
|
*
|
* @param paymentId 支付单号
|
* @param orderNo 订单号
|
* @return
|
*/
|
public static boolean refund(String paymentId, String orderNo) throws Exception {
|
JSONObject data = new JSONObject();
|
data.put("payment_id", paymentId);
|
data.put("order_no", orderNo);
|
JSONObject body = new JSONObject();
|
body.put("merId", MER_ID);
|
body.put("sign", sign(JSONObject.toJSONString(data)));
|
body.put("reqCipher",
|
EncryptUtils.aes256ECBPkcs7PaddingEncrypt(JSONObject.toJSONString(data), AES_KEY));
|
body.put("reqTime", DateUtils.dateTimeNow("yyyyMMddHHmmssfff"));
|
String result = sendPost(BASE_URL + PAYMENT_REFUND_INTERFACE, body);
|
JSONObject resJsonObject = JSONObject.parseObject(result);
|
if (resJsonObject.getString("status").equals("succeeded")) {
|
return true;
|
} else if (resJsonObject.getString("status").equals("failed")) {
|
throw new ServiceException(resJsonObject.getString("error_msg"));
|
}
|
return false;
|
}
|
|
/**
|
* 商户付款
|
*
|
* @param orderNo 订单号
|
* @param payAmt 交易金额
|
* @param cardName 收款银行开户名
|
* @param cardId 收款银行卡号
|
* @param cardType 收款银行账户类型 DEBIT_CARD:借记卡 CREDIT_CARD:贷记卡 76 QUASI_CREDIT_CARD:准贷卡 PASSBOOK:存折
|
* UNIT_SETTLE_CARD:单位结算卡 PUBLIC_CARD:对公卡
|
* @return
|
* @throws Exception
|
*/
|
public static boolean merchantPay(String orderNo, String payAmt, String cardName, String cardId,
|
String cardType)
|
throws Exception {
|
JSONObject data = new JSONObject();
|
data.put("order_no", orderNo);
|
data.put("pay_amt", payAmt);
|
data.put("card_name", cardName);
|
data.put("card_id", cardId);
|
JSONObject body = new JSONObject();
|
body.put("merId", MER_ID);
|
body.put("sign", sign(JSONObject.toJSONString(data)));
|
body.put("reqCipher",
|
EncryptUtils.aes256ECBPkcs7PaddingEncrypt(JSONObject.toJSONString(data), AES_KEY));
|
body.put("reqTime", DateUtils.dateTimeNow("yyyyMMddHHmmssfff"));
|
String result = sendPost(BASE_URL + MERCHANT_PAY_INTERFACE, body);
|
JSONObject resJsonObject = JSONObject.parseObject(result);
|
if (resJsonObject.getString("status").equals("succeeded")) {
|
return true;
|
} else if (resJsonObject.getString("status").equals("failed")) {
|
throw new ServiceException(resJsonObject.getString("error_msg"));
|
}
|
return false;
|
}
|
|
/**
|
* 发送post请求
|
*
|
* @param url 请求地址
|
* @param body 请求体
|
* @return
|
*/
|
private static String sendPost(String url, JSONObject body) {
|
HttpRequest post = HttpUtil.createPost(url);
|
Map<String, String> headers = new HashMap<>();
|
headers.put("Content-type", "application/json; charset=utf-8");
|
headers.put("Accept", "application/json");
|
post.addHeaders(headers);
|
post.body(body.toJSONString());
|
HttpResponse execute = post.execute();
|
String result = execute.body();
|
execute.close();
|
if (StringUtils.isBlank(result)) {
|
throw new ServiceException("请求第三方支付平台异常");
|
}
|
return result;
|
}
|
|
|
/**
|
* RSA私钥签名:签名方式SHA256WithRSA
|
*
|
* @param data 待签名字符串
|
* @return 签名byte[]
|
* @throws Exception
|
*/
|
public static String sign(String data) {
|
// 先对该json对象数据按照参数字典顺序(参数名ASCII码从小到大排序,参数名区分大小写)排序生成字符串,再进行加签和验签。
|
data = JSON.toJSONString(JSONObject.parseObject(data, TreeMap.class));
|
|
// Base64 --> Key
|
try {
|
byte[] bytes = Base64.getDecoder().decode(MERCHANT_PRIVATE_KEY);
|
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(bytes);
|
KeyFactory keyFactory;
|
keyFactory = KeyFactory.getInstance("RSA");
|
PrivateKey privateKey = keyFactory.generatePrivate(keySpec);
|
// Sign
|
Signature signature = Signature.getInstance("SHA256WithRSA");
|
signature.initSign(privateKey);
|
signature.update(data.getBytes("UTF-8"));
|
return Base64.getEncoder().encodeToString(signature.sign());
|
} catch (Exception e) {
|
e.printStackTrace();
|
return null;
|
}
|
}
|
|
}
|