小程序获取用户信息

官方文档: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());
}