最近在开发商户分润系统(给商户分红),涉及到给商户账号提现功能,我们使用的是支付宝转账,通过公钥证书方式实现的。
在支付宝开放平台里找了好久的开发文档,但是介绍更多的是普通公钥的方式,这个方式比较简单,而且是支付宝比较推荐的方式,但是支付宝官方对公钥证书方式的介绍我个人觉得不是很全面,我这里就记录一下我的解决方案吧,如有不足还请谅解。
这里只介绍编码部分,至于支付宝端应用创建,密钥以及证书等下载在此忽略,请自行百度,证书以后是这个的
CSR文件夹下面是应用密钥,应用公钥
第一步:导包
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.5.0.ALL</version>
</dependency>
- 当前仅Java版SDK(4.4.2.ALL及以上版本)支持证书签名方式,其他语言SDK还未支持。
- Java版SDK 4.4.2.ALL中并没有对APP支付场景添加证书支持,若业务使用到该场景,请下载4.4.5.ALL及以上版本的SDK。(建议使用高版本的jar包)
第二步:直接上代码
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.CertAlipayRequest;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayFundTransOrderQueryRequest;
import com.alipay.api.request.AlipayFundTransToaccountTransferRequest;
import com.alipay.api.response.AlipayFundTransOrderQueryResponse;
import com.alipay.api.response.AlipayFundTransToaccountTransferResponse;
import com.bustil.profit.entity.Alipay;
import com.bustil.profit.inface.base.ResponseConstant;
import com.bustil.profit.util.base.ResponseDataVo;
import com.google.gson.Gson;
@Component
public class AliPay {
//安全起见全部以配置文件方式
@Value("${alipay-config.CHARSET}")
private String CHARSET ;
@Value("${alipay-config.PAYEE_TYPE}")
private String PAYEE_TYPE ;
@Value("${alipay-config.APP_ID}")
private String APP_ID ;
@Value("${alipay-config.ALIPAY_URL}")
private String ALIPAY_URL ;
@Value("${alipay-config.APP_PRIVATE_KEY}")
private String APP_PRIVATE_KEY ;
//支付宝公钥证书文件路径
private static final String ALIPAY_CERT_PATH =".\\conf\\alipayCert\\alipayCertPublicKey_RSA2.crt";
//支付宝CA根证书文件路径
private static final String ALIPAY_ROOT_CERT_PATH = ".\\conf\\alipayCert\\alipayRootCert.crt";
//应用公钥证书路径
private static final String APP_CERT_PAHT = ".\\conf\\alipayCert\\appCertPublicKey_2019080****89.crt";
// public static void main(String[] args) {
// System.out.println("-----------------------------开始转账-----------------------------");
// try {
// //alipayTransfer();
// String tradingNo = "20190904****828275850"; //自己平台的唯一ID
// String amount = "0.1";
// String payeeAccount = "18*****3"; //这里填写收款人支付宝账号
// String remark = "测试转账";
// //alipayTransfer(tradingNo, amount, payeeAccount, remark);
// alipayFundTransOrderQuery(tradingNo);
// } catch (AlipayApiException e) {
// e.printStackTrace();
// }
// System.out.println("-----------------------------转账结束-----------------------------");
// }
//
/**
* 单笔转账到支付宝账号
* @author zhouhehe
* @param tradingNo 商户转账唯一订单号。发起转账来源方定义的转账单据ID,用于将转账回执通知给来源方。不同来源方给出的ID可以重复,同一个来源方必须保证其ID的唯一性。只支持半角英文、数字,及“-”、“_”。
* @param amount 转账金额,单位:元。只支持2位小数,小数点前最大支持13位,金额必须大于等于0.1元。
* @param payeeAccount 收款方账户。与payee_type配合使用。付款方和收款方不能是同一个账户。
* @param remark 转账备注(支持200个英文/100个汉字)。当付款方为企业账户,且转账金额达到(大于等于)50000元,remark不能为空。收款方可见,会展示在收款用户的收支详情中。
* @return
* @throws AlipayApiException
*/
public ResponseDataVo<Map<String, Object>> alipayTransfer(String tradingNo,String amount,String payeeAccount,String remark) throws AlipayApiException {
//构造client
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
certAlipayRequest.setServerUrl(ALIPAY_URL);
certAlipayRequest.setAppId(APP_ID);
certAlipayRequest.setPrivateKey(APP_PRIVATE_KEY);
certAlipayRequest.setFormat("json");
certAlipayRequest.setCharset(CHARSET);
certAlipayRequest.setSignType("RSA2");
//设置应用公钥证书路径
certAlipayRequest.setCertPath(APP_CERT_PAHT);
//设置支付宝公钥证书路径
certAlipayRequest.setAlipayPublicCertPath(ALIPAY_CERT_PATH);
//设置支付宝根证书路径
certAlipayRequest.setRootCertPath(ALIPAY_ROOT_CERT_PATH);
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayFundTransToaccountTransferRequest request = new AlipayFundTransToaccountTransferRequest();
Alipay alipay = new Alipay();
alipay.setOut_biz_no(tradingNo);
alipay.setPayee_type(PAYEE_TYPE);
alipay.setAmount(amount);
alipay.setPayer_show_name("******服务有限公司");
alipay.setPayee_account(payeeAccount);
//alipay.setPayee_real_name("哈哈哈哈");
alipay.setRemark(remark);
// 转成json格式放入
String json = new Gson().toJson(alipay);
request.setBizContent(json);
AlipayFundTransToaccountTransferResponse response = null;
Map<String, Object> map = new HashMap<String, Object>();
try {
response = alipayClient.certificateExecute(request);
if ("10000".equals(response.getCode())) {
map.put("code", response.getCode());
map.put("msg", response.getMsg());
map.put("subCode", response.getSubCode());
map.put("subMsg", response.getSubMsg());
map.put("tradingNo", response.getOutBizNo());
map.put("orderId", response.getOrderId());
map.put("payDate", response.getPayDate());
map.put("des", "转账成功");
return ResponseDataVo.success(map);
} else {
map.put("code", response.getCode());
map.put("msg", response.getMsg());
map.put("subCode", response.getSubCode());
map.put("subMsg", response.getSubMsg());
map.put("tradingNo", response.getOutBizNo());
map.put("orderId", response.getOrderId());
map.put("payDate", response.getPayDate());
map.put("des", "转账失败");
return new ResponseDataVo<Map<String,Object>>(map, ResponseConstant.ERROR_CODE, "转账失败");
}
} catch (AlipayApiException e) {
e.printStackTrace();
map.put("success", "false");
map.put("des", "转账失败!");
return new ResponseDataVo<Map<String,Object>>(map, ResponseConstant.ERROR_CODE, "转账失败");
}
}
/**
* 查询转账订单接口
* @author zhouhehe
* @param tradingNo 交易号 商户转账唯一订单号,分润系统唯一
* @return
* @throws AlipayApiException
*/
public ResponseDataVo<Map<String, Object>> alipayFundTransOrderQuery(String tradingNo) throws AlipayApiException {
// 构造client
CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
certAlipayRequest.setServerUrl(ALIPAY_URL);
certAlipayRequest.setAppId(APP_ID);
certAlipayRequest.setPrivateKey(APP_PRIVATE_KEY);
certAlipayRequest.setFormat("json");
certAlipayRequest.setCharset(CHARSET);
certAlipayRequest.setSignType("RSA2");
// 设置应用公钥证书路径
certAlipayRequest.setCertPath(APP_CERT_PAHT);
// 设置支付宝公钥证书路径
certAlipayRequest.setAlipayPublicCertPath(ALIPAY_CERT_PATH);
// 设置支付宝根证书路径
certAlipayRequest.setRootCertPath(ALIPAY_ROOT_CERT_PATH);
AlipayClient alipayClient = new DefaultAlipayClient(certAlipayRequest);
AlipayFundTransOrderQueryRequest request = new AlipayFundTransOrderQueryRequest();
Alipay alipay = new Alipay();
alipay.setOut_biz_no(tradingNo);
// 转成json格式放入
String json = new Gson().toJson(alipay);
request.setBizContent(json);
AlipayFundTransOrderQueryResponse response = null;
Map<String, Object> map = new HashMap<String, Object>();
try {
response = alipayClient.certificateExecute(request);
if ("10000".equals(response.getCode())) {
map.put("code", response.getCode());
map.put("msg", response.getMsg());
map.put("orderId", response.getOrderId());
map.put("payDate", response.getPayDate());
map.put("status", response.getStatus());
map.put("subCode", response.getSubCode());// 详情状态码
map.put("des", "转账成功");
return ResponseDataVo.success(map);
} else {
map.put("code", response.getCode());
map.put("msg", response.getMsg());
map.put("orderId", response.getOrderId());
map.put("payDate", response.getPayDate());
map.put("status", response.getStatus());
map.put("subCode", response.getSubCode());// 详情状态码
map.put("failReason", response.getFailReason());
map.put("des", "转账失败");
return new ResponseDataVo<Map<String,Object>>(map, ResponseConstant.ERROR_CODE, "转账失败");
}
} catch (AlipayApiException e) {
e.printStackTrace();
map.put("success", "false");
map.put("des", "转账失败!");
return new ResponseDataVo<Map<String,Object>>(map, ResponseConstant.ERROR_CODE, "转账失败");
}
}
}
这是一个测试demo,自测可用。
工具类添加一下:
package com.zhhtest.demozhh.inface;
public interface ResponseConstant {
/**返回编码:成功**/
Integer SUCCESS_CODE = 0;
/**失败**/
Integer ERROR_CODE = 1;
int SESSION_DISABLED = 2;//登录超时
int BUSINESS_ERROR = 3;//逻辑异常
int SYSTEM_ERROR = 4;//系统错误
int ACCESS_ERROR = 5;//无权限
int CHECK_CODE_ERROR = 6;//验证码错误
int TOKEN_NULL_ERROR = 7;//TOKEN为空
int ACCOUNT_NOT_EXIST = 8;//用户名不存在
int PASSWORD_ERROR = 9;//密码错误
int PARAMETEN_MISS = 10;//没有传必要的参数
int PARAMETEN_TYPE_ERROR = 11;//参数类型错误
/**返回信息:成功**/
String SUCCESS_MSG = "成功";
String ERROR_MSG = "失败";
String SESSION_DISABLED_MSG = "登录超时";
String BUSINESS_ERROR_MSG = "逻辑异常";
String SYSTEM_ERROR_MSG = "系统异常";
String ACCESS_MSG = "无权限";
String CHECK_CODE_ERROR_MSG = "验证码错误";
String TOKEN_NULL_ERROR_MSG = "登录信息已过期";
String ACCOUNT_NOT_EXIST_MSG = "用户不存在";
String PASSWORD_ERROR_MSG = "密码错误";
String PARAMETEN_MISS_MSG = "参数不完整";
String PARAMETEN_TYPE_ERROR_MSG = "参数类型错误";//参数类型错误
}
工具类2:
package com.zhhtest.demozhh.utils;
import com.zhhtest.demozhh.inface.ResponseConstant;
import java.io.Serializable;
public class ResponseBaseVo implements Serializable {
private static final long serialVersionUID = 4992866296675736795L;
/**
* 0 成功
* 1 失败
* 2 没有登录
*/
protected Integer code;
protected String message;
public ResponseBaseVo() {
}
public ResponseBaseVo(Integer code, String message) {
this.code = code;
this.message = message;
}
public static ResponseBaseVo success() {
return new ResponseBaseVo(ResponseConstant.SUCCESS_CODE, ResponseConstant.SUCCESS_MSG);
}
public static ResponseBaseVo erro() {
return erro(ResponseConstant.ERROR_MSG);
}
public static ResponseBaseVo erro(String message) {
return new ResponseBaseVo(ResponseConstant.ERROR_CODE, message);
}
public static ResponseBaseVo loginTimeOut(){
return new ResponseBaseVo(ResponseConstant.SESSION_DISABLED, ResponseConstant.BUSINESS_ERROR_MSG);
}
public static ResponseBaseVo logicalError(String msg){
return new ResponseBaseVo(ResponseConstant.BUSINESS_ERROR, msg);
}
public static ResponseBaseVo logicalError(){
return new ResponseBaseVo(ResponseConstant.BUSINESS_ERROR, ResponseConstant.BUSINESS_ERROR_MSG);
}
public static ResponseBaseVo systemError(String msg){
return new ResponseBaseVo(ResponseConstant.SYSTEM_ERROR, ResponseConstant.SYSTEM_ERROR_MSG);
}
public static ResponseBaseVo accessError(String msg){
return new ResponseBaseVo(ResponseConstant.ACCESS_ERROR, ResponseConstant.ACCESS_MSG);
}
public Integer getCode() {
return code;
}
public void setCode(Integer code) {
this.code = code;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
@Override
public String toString() {
return JsonUtil.toJson(this);
}
}
工具3:
package com.zhhtest.demozhh.utils;
import java.io.Serializable;
import com.zhhtest.demozhh.inface.ResponseConstant;
public class ResponseDataVo<T> extends ResponseBaseVo implements Serializable {
/**
*
*/
private static final long serialVersionUID = -8389534598865802502L;
private T data;
public ResponseDataVo() {
}
public ResponseDataVo(T data, Integer code, String message) {
super(code, message);
this.data = data;
}
public static <T> ResponseDataVo<T> success(T t) {
return new ResponseDataVo<T>(t, ResponseConstant.SUCCESS_CODE, ResponseConstant.SUCCESS_MSG);
}
public static <T> ResponseDataVo<T> error() {
return error(ResponseConstant.ERROR_MSG);
}
public static <T> ResponseDataVo<T> error(String message) {
return new ResponseDataVo<T>(null, ResponseConstant.ERROR_CODE, message);
}
public static <T> ResponseDataVo<T> logicError(String message) {
return new ResponseDataVo<T>(null, ResponseConstant.BUSINESS_ERROR, message);
}
public static <T> ResponseDataVo<T> sysError(String message) {
return new ResponseDataVo<T>(null, ResponseConstant.SYSTEM_ERROR, message);
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
平时不怎么写博客,如有不正确的地方还请指出