支付宝小程序
小程序获取用户信息
官方文档:https://docs.open.alipay.com/api_9/alipay.system.oauth.token
@GetMapping("/getUserInfo")
public JsonResult alipayUserInfoAuth(String authCode) {
// 1. 服务端获取access_token、user_id
AlipaySystemOauthTokenResponse response = null;
try {
response = getAccessToken(authCode);
if (response.isSuccess()) {
System.out.println("获取access_token - 调用成功");
/**
* 获取到用户信息后保存到数据
* 1. 如果数据库不存在对用的 alipayUserId, 则注册
* 2. 如果存在,则获取数据库中的信息再返回
*/
String accessToken = response.getAccessToken();
String alipayUserId = response.getUserId();
System.out.println("accessToken:" + accessToken);
System.out.println("alipayUserId:" + alipayUserId);
if (StringUtils.isNotBlank(alipayUserId)) {
//保存userID
UserWechat user = userWechatService.findUserWechatByOpenid(alipayUserId);
if (user == null) {
UserWechat userWechat = new UserWechat();
userWechat.setOpenId(alipayUserId);
userWechat.setFromSource(3);
userWechatService.insert(userWechat);
}
//返回值格式根据自己程序来就好,最主要是把alipayUserId返回出去
jsonResult.setCode(SysConst.JSON_RESULT_CODE_SUCCESS);
jsonResult.setResult(alipayUserId);
return jsonResult;
}
} else {
System.out.println("获取access_token - 调用失败");
}
} catch (Exception e) {
e.printStackTrace();
}
jsonResult.setCode(SysConst.JSON_RESULT_CODE_ERROR);
jsonResult.setMsg("获取用户信息失败");
return jsonResult;
}
// 服务端获取access_token、user_id
private AlipaySystemOauthTokenResponse getAccessToken(String authCode) throws Exception {
AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gateway, AlipayConfig.small_app_id, AlipayConfig.private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type);
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
request.setGrantType("authorization_code");
request.setCode(authCode);
request.setRefreshToken("201208134b203fe6c11548bcabd8da5bb087a83b");
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
return response;
}
小程序支付
AlipayConfig.java
/* *
*类名:AlipayConfig
*功能:基础配置类
*详细:设置帐户有关信息及返回路径
*修改日期:2017-04-05
*说明:
*以下代码只是为了方便商户测试而提供的样例代码,商户可以根据自己网站的需要,按照技术文档编写,并非一定要使用该代码。
*该代码仅供学习和研究支付宝接口使用,只是提供一个参考。
*/
public class AlipayConfig {
//↓↓↓↓↓↓↓↓↓↓请在这里配置您的基本信息↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
// APP应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
public static String APP_ID = "";
// 商户私钥,您的PKCS8格式RSA2私钥
public static String PRIVATE_KEY = "";
// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。
public static String ALIPAY_PUBLIC_KEY = "";
// 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String NOTIFY_URL = "";
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
public static String RETURN_URL = "";
// 签名方式
public static String SIGN_TYPE = "RSA2";
// 字符编码格式
public static String CHARSET = "utf-8";
// 支付宝网关
public static String GATEWAY = "https://openapi.alipay.com/gateway.do";
// 支付宝网关
public static String LOG_PATH = "C:\\";
//支付宝小程序AES密钥
public static String AES_KEY = "";
//小程序APPID
public static String SMALL_APP_ID = "";
public static String gateway_dev = "https://openapi.alipaydev.com/gateway.do";
//↑↑↑↑↑↑↑↑↑↑请在这里配置您的基本信息↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑
/**
* 写日志,方便测试(看网站需求,也可以改成把记录存入数据库)
*
* @param sWord 要写入日志里的文本内容
*/
public static void logResult(String sWord) {
FileWriter writer = null;
try {
writer = new FileWriter(log_path + "alipay_log_" + System.currentTimeMillis() + ".txt");
writer.write(sWord);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
官方文档:https://docs.open.alipay.com/api_1/alipay.trade.create
// 略
String APP_ID = AlipayConfig.APP_ID;
String APP_PRIVATE_KEY = AlipayConfig.PRIVATE_KEY;
String ALIPAY_PUBLIC_KEY = AlipayConfig.ALIPAY_PUBLIC_KEY;
//签名方式
String sign_type = "RSA2";
//编码格式
String CHARSET = "utf-8";
//正式环境支付宝网关,如果是沙箱环境需更改成https://openapi.alipaydev.com/gateway.do
String url = "https://openapi.alipay.com/gateway.do";
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(url, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, sign_type);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称: alipay.trade.create
AlipayTradeCreateRequest alipayRequest = new AlipayTradeCreateRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
//请保证OutTradeNo值每次保证唯一
alipayRequest.setBizContent("{" +
"\"out_trade_no\":\"" + 商户订单号 + "\"," +//可以随机生成订单号:String outTradeNo = UUID.randomUUID().toString().replace("-", "");
"\"total_amount\":" + 金额 + "," +
"\"subject\":\"" + 标题 + "\"," +
"\"enable_pay_channels\":\"balance,moneyFund,honeyPay,debitCardExpress,credit_group\"," +//这个是可以供用户选择的支付方式,直接用即可。常用的支付方式基本都开放了
"\"buyer_id\":\"" + 用户ID + "\"" +
"}");
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
AlipayTradeCreateResponse alipayResponse = null;
try {
//使用的是execute
alipayResponse = alipayClient.execute(alipayRequest);
if (!alipayResponse.isSuccess()) {
jsonResult.setCode(SysConst.JSON_RESULT_CODE_ERROR);
jsonResult.setMsg("支付宝调用失败");
return jsonResult;
}
} catch (Exception e) {
e.printStackTrace();
}
// 略
// 最后在处理完所有逻辑后将alipayResponse.getTradeNo()返回给前端即可
APP支付
自己开发的APP,或者字节跳动小程序接入支付宝支付就是接入的APP支付,和小程序支付没什么太大区别。用法基本一致,也就是使用的API变了罢了
官方文档:https://docs.open.alipay.com/api_1/alipay.trade.app.pay/
这里有个需要注意的地方,微信的金额单位是分,支付宝的金额单位是元
String APP_ID = AlipayConfig.APP_ID;
String APP_PRIVATE_KEY = AlipayConfig.PRIVATE_KEY;
String ALIPAY_PUBLIC_KEY = AlipayConfig.ALIPAY_PUBLIC_KEY;
//签名方式
String sign_type="RSA2";
//编码格式
String CHARSET="utf-8";
//正式环境支付宝网关,如果是沙箱环境需更改成https://openapi.alipaydev.com/gateway.do
String url="https://openapi.alipay.com/gateway.do";
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(url, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY,sign_type);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeAppPayRequest alipayRequest = new AlipayTradeAppPayRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
model.setBody("我是测试数据");
model.setSubject("App支付测试Java");
//请保证OutTradeNo值每次保证唯一
model.setOutTradeNo("2017090080001939235");
model.setTimeoutExpress("30m");
model.setTotalAmount("0.01");
model.setProductCode("QUICK_MSECURITY_PAY");
//设置可以支付的方式,比如余额,花呗之类的,自行百度
model.setEnablePayChannels("balance,moneyFund,pcredit,debitCardExpress");
alipayRequest.setBizModel(model);
alipayRequest.setNotifyUrl(AlipayConfig.notify_url);
try {
//这里和普通的接口调用不同,使用的是sdkExecute
AlipayTradeAppPayResponse alipayResponse = alipayClient.sdkExecute(alipayRequest);
System.out.println(alipayResponse.getBody());//就是orderString 可以直接给客户端请求,无需再做处理。
} catch (AlipayApiException e) {
e.printStackTrace();
}
支付回调
支付宝官方文档:https://opendocs.alipay.com/open/203/105286
解析流获取参数
/**
* 支付回调
*
* @param request
* @param response
* @return
*/
@RequestMapping("/url请求路径")
@ResponseBody
public String payResult(HttpServletRequest request, HttpServletResponse response) {
response.setHeader("Content-type", "text/html;charset=UTF-8");
try {
String reqParams = StreamUtil.read(request.getInputStream());
System.out.println("payResult支付回调结果:" + reqParams);
} catch (Exception e) {
e.printStackTrace();
}
return "SUCCESS";
}
- StreamUtil.java
public class StreamUtil {
public static String read(InputStream is){
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
int len = 0;
byte[] buffer = new byte[512];
while((len = is.read(buffer)) != -1){
baos.write(buffer, 0, len);
}
return new String(baos.toByteArray(), 0, baos.size(), "utf-8");
}catch (Exception e) {
e.printStackTrace();
}
return "";
}
}
直接获取
这里的参数名需要和支付宝返回的参数名一致才能成功获取
/**
* 支付宝支付回调
*
* @param request
* @param response
* @param out_trade_no 商户订单号
* @param trade_status 交易状态
* @param trade_no 支付宝订单号
* @return
*/
@RequestMapping("/url")
public String alipayCallback(HttpServletRequest request, HttpServletResponse response, String out_trade_no, String trade_status, String trade_no) {
response.setHeader("Content-type", "text/html;charset=UTF-8");
try {
System.out.println("alipayCallback交易订单号:" + out_trade_no);
System.out.println("alipayCallback交易状态:" + trade_status);
System.out.println("alipayCallback交易支付宝订单号:" + trade_no);
} catch (Exception e) {
e.printStackTrace();
}
return "SUCCESS";
}
退款
官方文档:https://docs.open.alipay.com/api_1/alipay.trade.refund
//支付宝退款
String APP_ID = AlipayConfig.APP_ID;
String APP_PRIVATE_KEY = AlipayConfig.PRIVATE_KEY;
String ALIPAY_PUBLIC_KEY = AlipayConfig.ALIPAY_PUBLIC_KEY;
//签名方式
String sign_type = "RSA2";
//编码格式
String CHARSET = "utf-8";
//正式环境支付宝网关,如果是沙箱环境需更改成https://openapi.alipaydev.com/gateway.do
String url = "https://openapi.alipay.com/gateway.do";
//实例化客户端
AlipayClient alipayClient = new DefaultAlipayClient(url, APP_ID, APP_PRIVATE_KEY, "json", CHARSET, ALIPAY_PUBLIC_KEY, sign_type);
//实例化具体API对应的request类,类名称和接口名称对应,当前调用接口名称:alipay.trade.app.pay
AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式(model和biz_content同时存在的情况下取biz_content)。
AlipayTradeRefundModel model = new AlipayTradeRefundModel();
//请保证OutTradeNo值每次保证唯一
model.setOutTradeNo(paymentRecord.getOutTradeNo());
model.setRefundAmount(paymentRecord.getTotalFee().toString());
model.setRefundReason("正常退款");
alipayRequest.setBizModel(model);
AlipayTradeRefundResponse alipayResponse = null;
try {
alipayResponse = alipayClient.execute(alipayRequest);
JSONObject jsonObject = JSONObject.fromObject(alipayResponse.getBody());
jsonObject = JSONObject.fromObject(jsonObject.get("alipay_trade_refund_response"));
//判断退款状态
if ("10000".equals(jsonObject.get("code")) && "Success".toUpperCase().equals(jsonObject.get("msg").toString().toUpperCase())) {
return "success";
}
} catch (Exception e) {
e.printStackTrace();
log.error("支付宝退款错误!" + e.getMessage());
}