最近在忙于做毕业设计,刚好用到支付宝充值功能,就过来写个帖子。
1.到支付宝网站注册账号
官网:https://openhome.alipay.com/platform/developerIndex.htm
2.点击研发服务进入沙箱环境
配置RSA2,推荐使用支付宝提供的密匙工具。同步异步接口也可以不设置,下文会在java代码中设置
这里异步调用接口需要公网可以访问,如果经济不允许的情况下可以使用花生壳内网穿透工具:
我的个人配置:开通HTTP协议需要花费6元永久域名
3.沙箱账号
用于登录沙箱版支付宝app测试
4.接入项目
创建一个配置类
/**
* @author 码农界的小学生
* @description:阿里支付配置信息
* @title: AliDevPayConfig
* @projectName graduation-project
* @description: TODO
* @date 2020/4/23 19:06
*/
@Configuration
public class AliDevPayConfig implements Serializable {
// 这个是支付完成后的跳转路径 可以是一个页面地址等
public static String returnUrl = "http://www.graduation.com/#/addIncoming";
//服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
// 这个是支付成功失败以后的通知接口会返回相应的参数
public static String notifyUrl = "http://3111h4q179.zicp.vip/cms/alipay/notify";
/**支付宝分配给开发者的应用ID*/
public static String aliPayAppId = "你的appid";
/**
* 商户id
*/
public static String uid = "2088102180918899";
/**支付宝网关*/
public static String aliPayGateWay = "https://openapi.alipaydev.com/gateway.do";
public static String mcloud_api_domain = "http://mcloudmonitor.com/gateway.do";
/**私钥*/
public static String aliPayPrivateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCtPPBOHRZyOPH2Qn4IAWmY+qrJaYSs5PZwRtAxm7oPcgChnacGr8uTZKtZtNFMwoI1RXqutWAWjMhVNHv9JcAdZbL7LsXO8AuP09YcFpGGXEWFoze3RGeN4Oiy1JhC21nkZONXn2RlmR44dHNLvH3p213MjR6omV16qG0SqFyCQ6m3DPVvXn+aclw+0vZPa6wvjKFn57WdgFrrwHSKMvuPoz5qW4Yv7wu4isXyOowczyfX0DERVvcdYdaIPUOEBEN6EcKbVq8/FC1zMq79REBU/iVtVjWunRe6FMq+jbzNsVvZdwm2FEG2hcnw+GmvZUMIstUf3dm3yZiMqULPCGf/AgMBAAECggEAdingx4czrkmFUTHdgVxlSMGCCMv+gWfTaJYEoDHWYX6jS5mbOgZi13CNKC0brj3mTqvLmKuClR8F7ohUIkHDnsmloYsvxY0adcpKevIx5PG/Qf4onMr9z1qfnotAKCoyUIU4RKYl9t7QLDXSBtDVGdRVUJbZWKrzhhyn+Vf5cafOyyQEgMAonAYqkLweZilyFO5TGlgLKJsKXhQjltZrPxVebQ9PowIz47NvQVOBya+WGTAkyN1Bri10ZLxr62VGhUjUGKcRL0qVxtaXpafARcW5HU1U/aJlkX9stHZwRlLsxdN5MV1DwlKInX9shYHOHheCsohlB7ZaZYmwrVulEQKBgQD1cmknrwkiYgocPq7NhQ89IddmWgduqkTE9FbaDXtM7YrvTIPGJDCE5d71R+sw8GG36M0OQxitdB72mbv6md+FxqmAtlD6d0L5V0mJfRErW4W48NhCI03XIWUcy3JrtqVF1N7qlB7D5IkW3DBqFVHf2iO97oMczhhsQsVnrH0VmwKBgQC0r7zyS6DwV1Pb8q3n1dmWD/wg4PuV35PC/uZ5CXiYWOcbaZZM1+3QQ56F/qZugwsb7aXbl7lL67hZ70GcQJPC8YBHebrBK9q/8C29TkPigzY0jWgM4rFbcb/raRKP3Oy1T4itIUH1/nuWwZT2AoT8lLRbLmeUeDCvg3GsbrhvbQKBgQCxhkvKOQ5pQPHBFhFGcsvf0l9CFzGy+BH/Rh6fXgrlTBYmGHhi0oAJT12gmKDiZ6q14vqVKzBpHEjc4bqVeb+yuUqV3sfZMHNPdrOobr4BVxPz/Lbdtz0wsWW5muiqQZNuW5XToshRtTT2RNH7mGn8d4FMeXt5VRNTEkRHRPm/qwKBgEXtGS+gCznYYhDmG110io+jwgyrZVI8Q4Aci+9dtfknttEKDOvSSSvnb2smAR0Vw+/cCesxDboPELpleLvS1hyEwANpXdgyc6cCeYEgz+7SnuC5tQH/nWnpXL/rWw6oDkeg7yEplNBx2zyd0Ftg4DysBByhmd6AoT7bnNuBwgkFAoGAVYXQYh+YgM5mKaagBZOWqwhkP4Pr8Oo44G5RaswP/O7R4ulgQ48BsaPifngek+tDTetX3nlZjogb1YtIEEJNJ1SSPsvEZGzR0cwgysp+wRjER5O+M2rvNWc3G+a4wM864eYuCq1n73xL9FqXYIJXjRlmLobejYiOqYa02bRIpQc=";
/**支付宝公钥 注意是支付宝公钥 不是应用公钥*/
public static String aliPayPublicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAix4U83rjS6rT8w8njXFEU+SAYH/zCCRQc98PpUDEBBx3qY7CaJPL0QPETs1WyufqZYRSKbW0Ml9wTA/SXgOp3bJn5v78vhe2LSFtmr0gCyNJXtSDrz91XgR/oK3T5j0yy8NgOMBjdjnI2a6cpqrt3YXkc02hhJTfG+3o6f+gGw6wtU7CC0BTGoH//lk+prNerjeFQLZd7hB0ANlC5JdSfDBHtr/+gPcL7ap84nEJA1TSOCnQP8h2UYd5MAwqwyqitK3B9hEUCWI7Mp3VgI+CAGVXXnUzL74hUK26yrTczucX9bEPUUAyrlxWIUZ3OsX07KwpL1PLnKH/HYJStFG8TQIDAQAB";
public static String FORMAT = "JSON";
/**请求使用的编码格式,如utf-8,gbk,gb2312等*/
public static String CHARSET = "utf-8";
/**商户生成签名字符串所使用的签名算法类型,目前支持RSA2和RSA,推荐使用RSA2*/
public static String SIGN_TYPE = "RSA2";
}
Controller:
/**
* @author 码农界的小学生
* @description:
* @title: PayController
* @projectName graduation-project
* @description: TODO
* @date 2020/4/23 21:39
*/
@RequestMapping("/cms/alipay")
@RestController
public class PayController implements PayControllerApi {
@Autowired
private PayService payService;
@Override
@RequestMapping(value = "/pay")
public String aliPay(@RequestParam("id")String id,
@RequestParam("type")String type,@RequestParam("money")String money) throws IOException {
return payService.aliPay(id,type,money);
}
@Override
@RequestMapping ("/notify")
public void payNotice(HttpServletRequest request,HttpServletResponse response) throws Exception {
payService.alipayNotify(request,response);
}
}
Service:
/**
* @author 码农界的小学生
* @description:调用支付宝接口业务逻辑
* @title: PayService
* @projectName graduation-project
* @description: TODO
* @date 2020/4/23 21:43
*/
@Service
public class PayService {
@Autowired
private OrderClient orderClient;
@Autowired
private OrderCollectionRepository orderCollectionRepository;
@Autowired
private SuperRepository superRepository;
@Autowired
private UserRoleRepository userRoleRepository;
@Autowired
private UserRepository userRepository;
/**
* 调用支付宝接口
* @return
*/
public String aliPay(String id,String type,String money) {
//非法参数 抛出异常
if(StringUtils.isEmpty(id) || StringUtils.isEmpty(type) || StringUtils.isEmpty(money)){
ExceptionCast.cast(CommonCode.INVALID_PARAM);
}
//实例化客户端(参数:网关地址、商户appid、商户私钥、格式、编码、支付宝公钥、加密类型),为了取得预付订单信息
AlipayClient alipayClient = new DefaultAlipayClient(AliDevPayConfig.aliPayGateWay,AliDevPayConfig.aliPayAppId,
AliDevPayConfig.aliPayPrivateKey,AliDevPayConfig.FORMAT,AliDevPayConfig.CHARSET,AliDevPayConfig.aliPayPublicKey,
AliDevPayConfig.SIGN_TYPE);
//实例化具体API对应的request类
AlipayTradePagePayRequest payRequest = new AlipayTradePagePayRequest();
payRequest.setNotifyUrl(AliDevPayConfig.notifyUrl);
payRequest.setReturnUrl(AliDevPayConfig.returnUrl);
//SDK已经封装掉了公共参数,这里只需要传入业务参数。以下方法为sdk的model入参方式
AlipayTradePagePayModel payModel = new AlipayTradePagePayModel();
//商户订单号
UUID uuid = UUID.randomUUID();
String uid = uuid.toString();
payModel.setOutTradeNo(uid);
//对一笔交易的具体描述信息。这里存储用户id
payModel.setBody(id);
//商品名称
payModel.setSubject(type);
//交易超时时间 这里的30m就是30分钟
payModel.setTimeoutExpress("30m");
//支付金额 后面保留2位小数点..不能超过2位
payModel.setTotalAmount(money);
// //电脑网站支付销售产品码,不同的支付方式productCode不同 销售产品码(固定值)
payModel.setProductCode("FAST_INSTANT_TRADE_PAY");
payRequest.setBizModel(payModel);
try {
// 这里和普通的接口调用不同,使用的是sdkExecute
//返回支付宝订单信息(预处理)
AlipayTradePagePayResponse alipayTradePagePayResponse = alipayClient.pageExecute(payRequest);
//就是orderString 可以直接给APP请求,无需再做处理。
String result = alipayTradePagePayResponse.getBody();
return result;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
/**
* 支付成功后接口回调 加上事务注解
* @param request
* @return
*/
@Transactional
public void alipayNotify(HttpServletRequest request, HttpServletResponse response) throws AlipayApiException, UnsupportedEncodingException {
//获取支付宝POST过来反馈信息
Map<String,String> params = new HashMap<String,String>();
Map requestParams = request.getParameterMap();
for (Iterator iter = requestParams.keySet().iterator(); iter.hasNext();) {
String name = (String) iter.next();
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签名验证
//切记alipaypublickey是支付宝的公钥,请去open.alipay.com对应应用下查看。
//boolean AlipaySignature.rsaCheckV1(Map<String, String> params, String publicKey, String charset, String sign_type)
boolean signVerified = AlipaySignature.rsaCheckV1(params, AliDevPayConfig.aliPayPublicKey, AliDevPayConfig.CHARSET,AliDevPayConfig.SIGN_TYPE);
if(signVerified){
//商户订单号
String uid = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//用户id
String userId = new String(request.getParameter("body").getBytes("ISO-8859-1"),"UTF-8");
//健身房会员卡类型
String type = new String(request.getParameter("subject").getBytes("ISO-8859-1"),"UTF-8");
//金额
String money = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
/*
这里编写业务逻辑
*/
}
}
}
5.项目调用支付宝接口流程
前端项目调用方法请求/cms/alipay/pay ,然后跳转到支付页面,支付完成后会同步跳转returnUrl返回到商品页面。支付宝支付后会异步请求notifyUrl,这里通过花生壳内网穿透工具代理到/cms/alipay/notify,然后完成业务逻辑。
6.效果图
点击会员充值调用对应的js方法:
submitPay(item){
if (!this.params.id){
this.$message.error("请先登录");
return ;
}
this.params.type = item.type;
this.params.money = item.money;
let querys = querystring.stringify(this.params);
window.location ="http://www.graduation.com/cms/alipay/pay?"+querys;
}
跳转到支付页面:
完成支付后自动跳转到原来页面:
哈哈,界面过于丑陋,咋们不要注重外表。前端页面基本上都是自己一点一点组装起来的,现在看到前端头疼,索性丑就丑点吧。
来源:oschina
链接:https://my.oschina.net/u/4419312/blog/4269906