支付宝小程序的支付和微信小程序的支付一样第一步都是要获取到用户的唯一标识,在微信中我们获取到的是wxopenid,而支付宝中获取到的是userid。
<!-- 使用的alipay-sdk包 -->
<dependency>
<groupId>com.alipay.sdk</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>4.5.0.ALL</version>
</dependency>
1.授权 前端使用 my.getAuthCode方法。
参考官方文档https://opendocs.alipay.com/mini/introduce/authcode
2.根据第一步的授权拿到auth_code来获取唯一标识userid。
/**
* 授权码
* @param auth_code
* @return
* @throws AlipayApiException
*/
@RequestMapping("getInfo")
public AjaxJson getInfo(String auth_code) throws AlipayApiException {
//使用支付宝小程序的固定方法获取auth_code
if(auth_code==null||auth_code.length()==0) {
return AjaxJson.getError("请求参数auth_code不能为空");
}else {
//String serverUrl, String appId, String privateKey, String format,String charset, String alipayPublicKey, String signType
//实例化客户端 参数:正式环境URL,Appid,商户私钥 PKCS8格式,字符编码格式,字符格式,支付宝公钥,签名方式
AlipayClient alipayClient = new DefaultAlipayClient("https://openapi.alipay.com/gateway.do",AliPayConfig.APP_ID,AliPayConfig.MERCHANT_PRIVATE_KEY,"json","GBK",AliPayConfig.ALIPAY_PUBLIC_KEY,"RSA2");
AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest();
// 值为authorization_code时,代表用code换取
request.setGrantType("authorization_code");
//授权码,用户对应用授权后得到的
request.setCode(auth_code);
//这里使用execute方法
AlipaySystemOauthTokenResponse response = alipayClient.execute(request);
//刷新令牌,上次换取访问令牌时得到。见出参的refresh_token字段
request.setRefreshToken(response.getAccessToken());
//返回成功时 就将唯一标识返回
if(response.isSuccess()){
System.out.println("调用成功");
//我这里只返回了一个字段给前端用
Map<String,Object> map=new HashMap<>();
map.put("userid", response.getUserId());
return AjaxJson.getSuccessData(map);
} else {
return AjaxJson.getError("调用失败");
}
}
}
3.获取用户信息 前端使用API中的方法 my.getOpenUserInfo 。获取到之后传给后端并调用接口保存或者更新用户信息。
注意:获取会员基础信息需要在开放平台小程序 管理页面 申请添加 获取会员基础信息 功能包。
/***
* 根据userid查询数据库是否有这个人,有就更新时间 没有就添加到数据库
* @param userid
* @param avatar
* @param countryCode
* @param province
* @param city
* @param nickName
* @param gender
* @return
*/
@RequestMapping("queryInfo")
public AjaxJson queryInfo(String userid, String avatar, String countryCode, String province, String city,
String nickName, String gender) {
Alipayuserinfo info = alipayuserinfoMapper.getInfoByUid(userid);
if (info != null) {
info.setUpdatetime(new Date());
alipayuserinfoMapper.update(info);
} else {
Alipayuserinfo userinfo = new Alipayuserinfo();
userinfo.setNick_name(nickName);
userinfo.setAvatar(avatar);
userinfo.setUserid(userid);
userinfo.setCountryCode(countryCode);
userinfo.setProvince(province);
userinfo.setCity(city);
userinfo.setGender(gender);
alipayuserinfoMapper.add(userinfo);
return AjaxJson.getSuccessData(userinfo);
}
return AjaxJson.getSuccessData(info);
}
这里肯定会有朋友不解授权和获取用户信息可以写在一个方法里而我写了两个方法,对的。我一开始是放在一起写的,但是测试的时候一直报出Isv权限不足,能解决的办法都试过了,继续报错。所以我是分开写了方法。
4.支付 官方文档https://opendocs.alipay.com/mini/introduce/pay
注意这里是官方文档中的代码
以下是我本人的代码
/**
* 用户唯一标识id
* @param userid
* @return
*/
@RequestMapping("/pay1")
public static AlipayTradeCreateResponse pay(String userid){
//获得初始化的AlipayClient
AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.GATEWAY_URL, AliPayConfig.APP_ID, AliPayConfig.MERCHANT_PRIVATE_KEY, "json", AliPayConfig.CHARSET, AliPayConfig.ALIPAY_PUBLIC_KEY, AliPayConfig.SIGN_TYPE);
//设置请求参数
AlipayTradeCreateRequest request = new AlipayTradeCreateRequest();
JSONObject json=new JSONObject();
//雪花算法订单号
IdWorker idworker=new IdWorker();
Long oid=idworker.nextId();
String out_trade_no =String.valueOf(oid);
//订单号
json.put("out_trade_no",out_trade_no);
//金额 这里的金额是以元为单位的可以不转换但必须是字符串
json.put("total_amount","0.01");
//描述
json.put("subject","测试");
//用户唯一标识id 这里必须使用buyer_id 参考文档
json.put("buyer_id",userid);
//对象转化为json字符串
String jsonStr=json.toString();
//商户通过该接口进行交易的创建下单
request.setBizContent(jsonStr);
//回调地址 是能够访问到的域名加上方法名
request.setNotifyUrl("http://vvvvvvv.cn/aliPay/notifyUrl");
try {
//使用的是execute
AlipayTradeCreateResponse response = alipayClient.execute(request);
return response;
} catch (AlipayApiException e) {
e.printStackTrace();
}
return null;
}
我在这里有一些代码没有使用官方文档的方式写参数,是因为我一开始写的时候去测试时一直返回参数无效,而我找了好久也不知道是什么原因,这就很尴尬了,所以我换了一种方式。大家写到这个地方的话可以参考。
前端调用my.tradePay方法
注意这里的trandeNo参数不用改,这是固定的,订单号需要你自己去支付那里获取。切记:获取到的值是trade_no,并不是outTradeNo。这是本人调试时的图,接下来离成功就不远了。
5.回调方法
/**
* 支付宝服务器异步通知url
* @throws Exception
*/
@RequestMapping(value="/notifyUrl")
public void notifyUrl(HttpServletRequest request,HttpServletResponse response) throws Exception{
//获取支付宝发送过来的信息
Map<String,String> params = new HashMap<String,String>();
Map<String,String[]> requestParams = request.getParameterMap();
//循环获取到所有的值
for(String str:requestParams.keySet()) {
String name =str;
String[] values = (String[]) requestParams.get(name);
String valueStr = "";
for (int i = 0; i < values.length; i++) {
valueStr = (i == values.length - 1) ? valueStr + values[i]
: valueStr + values[i] + ",";
}
//乱码解决,这段代码在出现乱码时使用
//valueStr = new String(valueStr.getBytes("ISO-8859-1"), "utf-8");
params.put(name, valueStr);
}
//调用SDK验证签名
boolean signVerified = AlipaySignature.rsaCheckV1(params, AliPayConfig.ALIPAY_PUBLIC_KEY, AliPayConfig.CHARSET, AliPayConfig.SIGN_TYPE);
//boolean类型signVerified为true时 则验证成功
if(signVerified) {
//获取到支付的状态 TRADE_SUCCESS则支付成功
String trade_status =request.getParameter("trade_status");
if (trade_status.equals("TRADE_SUCCESS")){
System.out.println("支付成功");
}else {
System.out.println("支付失败");
}
}
//签名验证失败
else {
System.out.println(AlipaySignature.getSignCheckContentV1(params));
}
}
}
6.退款 https://opendocs.alipay.com/apis/api_1/alipay.trade.refund/
官方的示例代码
这里的AlipayTradeRefundRequest 我没找到所以用的是另外一个类AlipayTradeRefundModel,可能是包的原因导致这个包一直没找到。大家写的时候要注意哈!
以下是本人的代码
/**
* 订单号
* @param outTradeNo
*/
@RequestMapping("alipayRefound")
public void alipayRefound(String outTradeNo) {
//初始化
AlipayClient alipayClient = new DefaultAlipayClient(AliPayConfig.GATEWAY_URL, AliPayConfig.APP_ID, AliPayConfig.MERCHANT_PRIVATE_KEY, "json", AliPayConfig.CHARSET, AliPayConfig.ALIPAY_PUBLIC_KEY, AliPayConfig.SIGN_TYPE);
//构造退款的参数
AlipayTradeRefundModel model=new AlipayTradeRefundModel();
//订单号 这里的订单号是自己用算法生成的 和支付宝系统的订单号TradeNo只能二选一
model.setOutTradeNo(outTradeNo);
//系统订单号
//model.setTradeNo(tradeNo);
//金额
model.setRefundAmount("0.01");
//退款原因
model.setRefundReason("测试退款");
//退款请求
AlipayTradeRefundRequest request=new AlipayTradeRefundRequest();
//参数set到请求里
request.setBizModel(model);
try {
//退款返回
AlipayTradeRefundResponse response=alipayClient.execute(request);
System.out.println(response.getBody()+"\n");//获取到body这个订单的所有信息
System.out.println(response.getMsg()); //这里打印的是退款的信息 是否退款成功的原因
} catch (AlipayApiException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
System.out.println("支付宝退款错误");
}
}
本人测试时的图片