支付宝H5手机网站支付
首先
首先我用的是springboot2+spring cloud+eureka微服务做开发
(1)先配置application.yml,在里面配置支付宝相关配置
配置代码(这里面需要自己去支付宝开发平台https://openhome.alipay.com/platform/developerIndex.htm,自己去创建应用,具体申请方法请自行百度)
#阿里支付的一些参数
ali:
#应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
#appid
app_id:
#商户私钥,您的PKCS8格式RSA2私钥
merchant_private_key:
#支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm
# 对应APPID下的支付宝公钥。
alipay_public_key:
#服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
notify_url:
#页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
return_url:
#签名方式
sign_type: RSA2
#字符编码格式
charset: UTF-8
#支付宝网关
gatewayUrl: https://openapi.alipaydev.com/gateway.d
(2)配置AlipayConfig
package com.showtime.serviceenergize.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* @Author cjb
* @Date 2020/1/2 15:15
* @Description //TODO 支付宝支付的一些配置
*/
@Data
@Component
@ConfigurationProperties(prefix = "ali")
public class AlipayConfig {
// 应用ID,您的APPID,收款账号既是您的APPID对应支付宝账号
private String app_id;//例:2016082600317257
// 商户私钥,您的PKCS8格式RSA2私钥
private String merchant_private_key;
// 支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm
// 对应APPID下的支付宝公钥。
private String alipay_public_key;
// 服务器异步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
/**
* 返回的时候此页面不会返回到用户页面,只会执行你写到控制器里的地址
*/
private String notify_url;
// 页面跳转同步通知页面路径 需http://格式的完整路径,不能加?id=123这类自定义参数,必须外网可以正常访问
/**
* 此页面是同步返回用户页面,也就是用户支付后看到的页面,上面的notify_url是异步返回商家操作,谢谢
* 要是看不懂就找度娘,或者多读几遍,或者去看支付宝第三方接口API,不看API直接拿去就用,遇坑不怪别人
*/
private String return_url;
// 签名方式
private String sign_type;
// 字符编码格式
private String charset;
// 支付宝网关
private String gatewayUrl;
private String format = "json";
}
(2)开写具体实现代码
package com.showtime.serviceenergize.controller;
import com.showtime.common.model.dto.ResponseJsonCode;
import com.showtime.serviceenergize.entity.dto.PayDto;
import com.showtime.serviceenergize.service.AliPayService;
import com.showtime.serviceenergize.utils.JedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
/**
* @Author cjb
* @Date 2020/1/2 15:15
* @Description //TODO 支付宝支付的控制类
*/
@Api(tags = "(书唐赋能)-支付宝支付接口(*有修改2020-1.14)")
@RestController
@Slf4j
@RequestMapping("/ali/pay")
public class AlipayController {
/**
* 支付宝支付的service
*/
@Autowired
private AliPayService payService;
/**
* 快捷支付调用支付宝支付接口
*
* @return
* @throws Exception
*/
@ApiOperation(value = "(赋能手机H5支付接口)-支付宝创建订单", notes = "赋能手机H5支付接口)-支付宝创建订单")
@PostMapping("/create")
public ResponseJsonCode create(@RequestBody PayDto pay,HttpServletRequest request)
throws Exception {
return payService.create(pay);
}
/**
* p2p后台返回的操作(支付成功后,支付宝返回的数据)
*
* @param response
* @param request
* @throws Exception
*/
@RequestMapping("/notify_url")
public String notify(HttpServletResponse response, HttpServletRequest request) throws Exception {
return payService.notify(response,request);
}
/**
* 同步通知的页面的Controller(支付成功后跳转的界面或者操作)
*
* @return
* @throws InterruptedException
*/
@RequestMapping("/return_url")
public void Return_url(HttpServletResponse response,HttpServletRequest request) throws InterruptedException {
}
}
(2.1)AliPayService
package com.showtime.serviceenergize.service;
import com.showtime.common.model.dto.ResponseJsonCode;
import com.showtime.serviceenergize.entity.dto.PayDto;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* @Author cjb
* @Date 2020/1/2 15:15
* @Description //TODO 支付宝支付的service
*/
public interface AliPayService {
/**
* 创建订单
*
* @param schId 学校ID
* @param uId 用户id
* @param option 日 周 月
* @return
* @throws Exception
*/
ResponseJsonCode create(PayDto pay) throws Exception;
/**
* 异步通知
*
* @param response
* @param request
* @throws Exception
*/
String notify(HttpServletResponse response, HttpServletRequest request) throws Exception;
}
(2.2)AliPayService
package com.showtime.serviceenergize.service.impl;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeWapPayResponse;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.showtime.common.model.dto.ResponseJsonCode;
import com.showtime.common.utils.JudgeNumberUtil;
import com.showtime.serviceenergize.config.AlipayConfig;
import com.showtime.serviceenergize.entity.StEnergizeOrder;
import com.showtime.serviceenergize.entity.StEnergizeUserUnlockSchool;
import com.showtime.serviceenergize.entity.dto.PayDto;
import com.showtime.serviceenergize.mapper.GetSchoolPriceSlaveMapper;
import com.showtime.serviceenergize.mapper.StEnergizeOrderMapper;
import com.showtime.serviceenergize.mapper.StEnergizeUserUnlockSchoolMapper;
import com.showtime.serviceenergize.service.AliPayService;
import com.showtime.serviceenergize.utils.DateUtil;
import com.showtime.serviceenergize.utils.JedisUtil;
import com.showtime.serviceenergize.utils.UUIDUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
/**
* @Author cjb
* @Date 2020/1/2 15:15
* @Description //TODO 支付宝支付的service实现类
*/
@Transactional(rollbackFor = Exception.class)
@Slf4j
@Service
public class AliPayServiceImpl implements AliPayService {
/**
* 支付宝支付的一些配置
*/
@Autowired
private AlipayConfig alipayConfig;
/**
* 获取学校价格信息
*/
@Autowired
private GetSchoolPriceSlaveMapper slaveMapper;
/**
* 订单表 Mapper
*/
@Autowired
private StEnergizeOrderMapper orderMapper;
/**
* 用户解锁时限表 Mapper
*/
@Autowired
private StEnergizeUserUnlockSchoolMapper unlockSchoolMapper;
/**
* 创建订单
* @return
* @throws Exception
*/
@Override
public ResponseJsonCode create(PayDto pay) throws Exception {
JudgeNumberUtil.isPositiveNumericIntegration(pay.getSchId());
JudgeNumberUtil.isPositiveNumeric(pay.getUserNumber());
JudgeNumberUtil.isPositiveNumeric(pay.getCtIdentificationCode());
//将订单参数存入redis中,在支付宝支付成功时候调用
JedisUtil.setObject("alipay",pay);
AlipayClient alipayClient = new DefaultAlipayClient(
alipayConfig.getGatewayUrl(),
alipayConfig.getApp_id(),
alipayConfig.getMerchant_private_key(),
"json",
"utf-8",
alipayConfig.getAlipay_public_key(),
"RSA2");
AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
//随机生成订单号
String orderNo = System.currentTimeMillis() + "" + pay.getUserNumber() + "" + (int) ((Math.random() * 9 + 1) * 1000) + "";
System.out.println("订单编号:" + orderNo);
//------------------------------------------封装参数开始(具体需要的参数请看api文档)--------------------------------------------
AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
// 订单名称,必填
model.setSubject("充值积分");
//订单号
model.setOutTradeNo(orderNo);
// 付款金额,必填
model.setTotalAmount(getSchoolPrice(pay.getSchId(), pay.getOption()) + "");
// 销售产品码 必填
model.setProductCode("QUICK_MSECURITY_PAY");
// 商品描述,可空
model.setBody("飒飒飒飒");
request.setBizModel(model);
request.setReturnUrl(alipayConfig.getReturn_url());
request.setNotifyUrl(alipayConfig.getNotify_url());
AlipayTradeWapPayResponse wapPayResponse = alipayClient.pageExecute(request);
if (wapPayResponse.isSuccess()) {
String body = wapPayResponse.getBody();
//将信息存入订单,订单对象
StEnergizeOrder order = new StEnergizeOrder();
//UUid
order.setOrderId(UUIDUtil.getUuid());
//订单创建时间
order.setOrderCreationTime(System.currentTimeMillis()+"");
//商户好
order.setCtIdentificationCode(pay.getCtIdentificationCode());
//商户用户账号
order.setUserNumber(pay.getUserNumber());
//学校id
order.setSchId(pay.getSchId());
//支付方式(1-支付宝,2-微信)
order.setOrderMode(pay.getOrderMode());
if (pay.getOption() == 1) {
//购买天数
order.setPreOption(1);
} else if (pay.getOption() == 2) {
//购买天数
order.setPreOption(7);
} else if (pay.getOption() == 3) {
//购买天数
order.setPreOption(30);
}
//需付金额
order.setOrderMoney(getSchoolPrice(pay.getSchId(), pay.getOption()));
//订单编号
order.setOrderReference(orderNo);
//订单状态(1-已完成,2-未完成)
order.setOrderStatu(2);
orderMapper.insert(order);
return ResponseJsonCode.successRequestMsg("请求成功", body);
} else {
System.out.println("调用失败");
return null;
}
}
/**
* 回调参数(将支付成功的信息存入对应的订单表中)
*
* @param response
* @param request
* @return
* @throws Exception
*/
@Override
public String notify(HttpServletResponse response, HttpServletRequest request) throws Exception {
System.out.println("----------------------------notify_url------------------------");
// 交易状态
String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"), "UTF-8");
if ("TRADE_SUCCESS".equals(tradeStatus)) {
Map<String, String[]> requestMap = request.getParameterMap();
Map<String, String> paramsMap = new HashMap<>(16);
requestMap.forEach((key, values) -> {
String strs = "";
for (String value : values) {
strs = strs + value;
}
paramsMap.put(key, strs);
});
//根据订单号获取订单
StEnergizeOrder order = orderMapper.selectOne(new QueryWrapper<StEnergizeOrder>().eq("order_reference", paramsMap.get("out_trade_no")));
//将用户解锁信息存入
StEnergizeUserUnlockSchool unlockSchool = new StEnergizeUserUnlockSchool();
if (order != null) {
//交易流水号
order.setTranOrderNum(paramsMap.get("trade_no"));
//实付金额
String tradeNo = paramsMap.get("total_amount");
if (tradeNo != null) {
BigDecimal payMoney = new BigDecimal(tradeNo);
order.setPayMoney(payMoney);
}
//订单创建时间
String gmtCreate = paramsMap.get("gmt_create");
order.setOrderCreationTime(DateUtil.timesTamp(gmtCreate));
//解锁时间
String gmtPayment = paramsMap.get("gmt_payment");
order.setPurchasingTime(timesTamp);
unlockSchool.setSeuStartTime(timesTamp);
calendar.setTime(unlockTime);
Date time = null;
String toStr = null;
//订单支付时间
String payTime = paramsMap.get("gmt_payment");
String payDateTime = DateUtil.timesTamp(payTime);
order.setOrderPayTime(payDateTime);
//订单状态(1-已完成,2-未完成)
order.setOrderStatu(1);
//修改对象
orderMapper.update(order, new UpdateWrapper<StEnergizeOrder>().eq("order_reference", paramsMap.get("out_trade_no")));
unlockSchool.setCtIdentificationCode(order.getCtIdentificationCode());
unlockSchool.setSchId(order.getSchId());
unlockSchool.setUserNumber(order.getUserNumber());
unlockSchool.setSeuId(UUIDUtil.getUuid());
//将用户解锁信息存入\修改
StEnergizeUserUnlockSchool unlockSchool1 = unlockSchoolMapper.selectOne(new QueryWrapper<StEnergizeUserUnlockSchool>().eq("ct_identification_code", order.getCtIdentificationCode()).eq("user_number", order.getUserNumber()).eq("sch_id",order.getSchId()));
if (unlockSchool1 == null){
unlockSchoolMapper.insert(unlockSchool);
}else {
unlockSchoolMapper.update(unlockSchool,new UpdateWrapper<StEnergizeUserUnlockSchool>().eq("seu_id",unlockSchool1.getSeuId()));
}
} else {
return "fail";
}
// //调用SDK验证签名
// try {
// boolean whether = AlipaySignature.rsaCheckV1(paramsMap, alipayConfig.getAlipay_public_key(), alipayConfig.getCharset(), alipayConfig.getSign_type());
// } catch (AlipayApiException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// System.out.println("*********************验签失败********************");
// return "fail";
// }
return "success";
}
return "fail";
}
/**
* <p>方法说明: TODO 获取学校价格
* <p>参数说明: String notifyUrl 回调地址
* <p>参数说明: String body 商品描述
* <p>返回说明: Map<String,Object>
* <p>创 建 人: cjb
**/
private BigDecimal getSchoolPrice(Integer schId, Integer option) {
BigDecimal mony = null;
switch (option) {
case 1:
mony = slaveMapper.getSchoolPrice("mony_day", schId);
break;
case 2:
mony = slaveMapper.getSchoolPrice("mony_week", schId);
break;
case 3:
mony = slaveMapper.getSchoolPrice("mony_month", schId);
break;
default:
mony = new BigDecimal(0);
}
return mony;
}
}
总结
1:商户的appId一定要正确
上面是上线的应用appid,如果是测试沙箱直接进入沙箱测试界面
这三个都是需要配置在application.yml里面
2:配置秘钥需要下载支付宝密钥生成工具(https://docs.open.alipay.com/291/105971),下载完成后生成密钥
2.1:然后设置密钥 支付宝公钥是他自动生成的你不用管,只需要输入生成的应用公钥,再将应用私钥配置进application.yml里面
3:为了保证application.yml里面应用私钥和管理平台设置的应用私钥是正确的建议在工具里面核对下:匹配成功则没问题
4:沙箱测试没问题,只需要把两个回调换成你上线的域名,把appid换成你审核通过的应用app,把支付宝网关换成线上的即可