T之家 7 月 4 日消息 随着首个 Win11 预览版的发布,全新的微软商店现已上线,并将在今年晚些时候开始向主流用户推出。
在 6 月 24 日的发布会上,微软表示 Windows 11 商店已经经过了“从头到脚重新设计”。整个界面都进行了更新,滚动速度更快,还为更多内容增加了空间。据微软官方称,用户操作更简单,HTML 组件也已经被砍掉了。
在 Windows 10 上,微软商店的前端部分构建于 HTML/CSS (web 组件) 中。例如产品页面完全基于 html,虽然兼容性高一点但这大大降低了用户体验,尤其是当用户点击“获取”或“安装”按钮时还会崩溃。
例如,之前有网友反馈称下载大文件时大概率会失败,而且错误代码还没有给出任何解释。
在 Windows 11 中,微软将用 XAML/c# 语言编写的全新商店取代现有的商店,据微软官方员称,它是完全“UWP”的。
据称,新版应用商店的性能得到了显著改善,例如下载不再出现之前出现的中、大型应用和游戏的下载失败问题。一些不愿透露姓名的消息人士也证实,用户在新版商店中下载大型游戏的速度也变得更快。
通过 Windows 11,微软也在尝试改变其 Microsoft Store 的商业模式。
该公司希望所有开发者都去尽可能为 Microsoft Store 开发应用程序和游戏,而开发者现可使用自己的第三方商业支付系统,相对来说更加宽容和自由。
IT之家了解到,微软还支持通过添加更多使用不同框架创建的应用和游戏来扩展 Store 目录。微软 Teams 和 Visual Studio 预计将在今年年底上线全新商店。
值得一提的是,Adobe, Zoom, OBS Studio 和 Canva 等著名应用现已上架微软新版 Microsoft Store。
此外,Windows Insider 体验者可以通过使用旧版商店手动更新来下载新设计的 Microsoft Store。当然,虽然商店已经经过重新设计,但一些功能,如通过亚马逊应用商店 整合 Android 应用的功能仍未上线。
微软还表示,Windows 10 用户将在今年晚些时候获得相同的商店体验,其商店的质量将在未来几个月得到显著提高,例如搜索结果将不再包括低质量的指南/教程等内容。
:简介
电脑支付常用于电商和后台管理系统的账户充值等场景。
电脑网站支付 文档
电脑网站支付流程图
集成前需要先创建应用、配置密钥、回调地址等以及alipay-sdk-java.jar和alipay-trade-sdk.jar请查看Spring Boot入门教程(三十五):支付宝集成-准备工作
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<!-- alipay begin -->
<dependency>
<groupId>com.alipay</groupId>
<artifactId>alipay-sdk-java</artifactId>
<version>20170725114550</version>
</dependency>
<dependency>
<groupId>com.alipay</groupId>
<artifactId>alipay-trade-sdk</artifactId>
<version>20161215</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
<version>1.10</version>
</dependency>
<dependency>
<groupId>com.google.zxing</groupId>
<artifactId>core</artifactId>
<version>3.2.1</version>
</dependency>
<!-- alipay end -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
</dependencies>
# 沙箱账号
pay:
alipay:
gatewayUrl: https://openapi.alipaydev.com/gateway.do
appid: 2016091400508498
appPrivateKey: MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCtXKWs+trRSuCxEUvlsEeSAuLWs3B/Dh74R8223BnfzoA29aGeoycAqfKlBMcbzU2G1KayESvZKGpwBLeejSbecRYjgZsQDyEaDimQQJtGFvZVV6u4XNnvIJ72eQzEaEIQfuiorjBTLm6DQuds4R0GxftqON6QFoIZkWB9ZrZKd02cuy16dW+UqtLVGGAHcCIAkB63zUiKSNfweMddneZ7MVs3lvu3xhMnD+5us/+n2Vp4qhfmpYLcdqIW6InU4GypeoOpyUTrfUGpgdR0l924vHy/GQJZEKFaRcK3cYK+ECyKpSIoqaJJFLHbkqsliuPpMUG+rM3jiqeIAH4psAznAgMBAAECggEBAJ5jyEbbxrJzrAh7GhHX1fwUQPYSadTbrPYAfHX2cHlnrQMJtsk+nTLhEv0r+VJwZ8WpYkfMong8kcqYtL7ajcmsHqMAFhE9EWxBxj2ymWsXLabZe93sj30IG9Rq0nxcGQgDO0RqKWLGSFgK93Al2KRInKT3InkY53K+vR61ihVLmGf7+GwPtIZteBy+tuAyvcj2RlkYvjiFi3ySyZ1wA3sJIlgrGiixd6fj20XFGNE3CnAwu0BJgXXbP/S9J4C0RRa3ZXj8fX7oONhVxz2xKxn7AT4e8OWjt7J41H2LRct8Fgl9pqgz2FJYv/WfbkG8x9fGiKYYvPXoxjjrk/tkewkCgYEA8f9Lcu5JPrE9rpw9zlwhm5cOO81xLxdwL5R5/1bRP48BZGIYuqlCbVvjJVqtO8eTnLhUwH7fG8B7cmoeO9bGr9GQrtfyCqz6FtVymTBieJlfgZDVhtzyv2qKOBMIFE8jsbSBK/NHHMvykJ+XdQ1riwCeQDdXICRuYTTFwGk2OsUCgYEAt2SoN95tVmVrvKG6ATLNEtge/ozeVywA4GjltrSw/G9vqp+DkkT2pY19uROuzMazoTzKWpPho2q/qzNlv/ANbOFM2GEmKamQ7CO88JgRxMsPTvc/HxCLU/ClMJU8LcOf9LfP2KYZpPwuheKJoF4vDGj8NsbFmccJyYSdpkNEk7sCgYBJlL2FMaz1sgC2Ue19DIhvfaunRV1P20mSPgwmNmijccETm7w3LXX0OIdFeV/JGHLqqSWj7i+6iXk/ncKZoUGCfi8G6sQ+uL/GJ5qTt6GJV+ExTS+PtSjeSO/EAw1m13Vb+C16hpstx1l23f+4aJ81gbecgPct38XsKpaiXZtOnQKBgQCMsN7QRYYxwoq9YoDUzIlAzKYyeBVWYL6najHYUZR5hG/xQIBqZRem9/4cTvpJxKInrwA6LrrqaEl0aHDFp75U6h7O3PCvA5PXZK9dD/yJsZIj7U/yX/nTQokn1UUegrYiwiTkusBvrrtuINWePsLvTVc4GpObHnPmsiNTWsWwYwKBgENaeTNOCHV2km/ysXQSEIhKbtlAMQPsgWHCt/bzHlF9m18izb1LrJyjzcSsd+Zy78R+pv4G50Q27c3e/DFPz/wYxN/yHWRbyLBA8ipJbCtMtPEdS9krpmN6cChIdLGbz4CVUqOPSRzNb9lhhgPCcCNRq6DG3HBceb1Se9VnO3zk
alipayPublicKey: MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEApFQKccMq+wPoWh93DcX3XYrnT7FJ3gntJA/jEwgk6Jd3iEVS2CyUCCgFVcQn8xjXT81YbZHYvoC50IBuu+A+Ey+J8VIgsBm5g9uwbOLRf66GrZjuKOlalHm5gHXjcL2gZRMBJEStOxstcO2YQriqhQzdL3EKp+HQc9u14IOVFpZdR8qq1l7CzKHn1vQo/1fUPfUrTLQqSuQTU9Ospv/QHFqOJA7DPetUQ+jnaZ082f3clr4ITw4EE8A6IWqTXcETTx5j/udCGP84g2Y4j+8i9DqYGyD5ePVgt4G0ICBX1bi1qNlylfxRg8Y3c1DFrRGyr0NpKQxSVXkYaVNvrCoudQIDAQAB
returnUrl: http://s9v2cw.natappfree.cc/alipay/return
notifyUrl: http://s9v2cw.natappfree.cc/alipay/notify
spring:
thymeleaf:
prefix: classpath:/templates/
suffix: .html
mode: HTML5
encoding: UTF-8
/**
* 支付宝支付的参数配置
*
* @author mengday zhang
*/
@Data
@Slf4j
@ConfigurationProperties(prefix = "pay.alipay")
public class AlipayProperties {
/** 支付宝gatewayUrl */
private String gatewayUrl;
/** 商户应用id */
private String appid;
/** RSA私钥,用于对商户请求报文加签 */
private String appPrivateKey;
/** 支付宝RSA公钥,用于验签支付宝应答 */
private String alipayPublicKey;
/** 签名类型 */
private String signType = "RSA2";
/** 格式 */
private String formate = "json";
/** 编码 */
private String charset = "UTF-8";
/** 同步地址 */
private String returnUrl;
/** 异步地址 */
private String notifyUrl;
/** 最大查询次数 */
private static int maxQueryRetry = 5;
/** 查询间隔(毫秒) */
private static long queryDuration = 5000;
/** 最大撤销次数 */
private static int maxCancelRetry = 3;
/** 撤销间隔(毫秒) */
private static long cancelDuration = 3000;
private AlipayProperties() {}
/**
* PostContruct是spring框架的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。
*/
@PostConstruct
public void init() {
log.info(description());
}
public String description() {
StringBuilder sb = new StringBuilder("\nConfigs{");
sb.append("支付宝网关: ").append(gatewayUrl).append("\n");
sb.append(", appid: ").append(appid).append("\n");
sb.append(", 商户RSA私钥: ").append(getKeyDescription(appPrivateKey)).append("\n");
sb.append(", 支付宝RSA公钥: ").append(getKeyDescription(alipayPublicKey)).append("\n");
sb.append(", 签名类型: ").append(signType).append("\n");
sb.append(", 查询重试次数: ").append(maxQueryRetry).append("\n");
sb.append(", 查询间隔(毫秒): ").append(queryDuration).append("\n");
sb.append(", 撤销尝试次数: ").append(maxCancelRetry).append("\n");
sb.append(", 撤销重试间隔(毫秒): ").append(cancelDuration).append("\n");
sb.append("}");
return sb.toString();
}
private String getKeyDescription(String key) {
int showLength = 6;
if (StringUtils.isNotEmpty(key) && key.length() > showLength) {
return new StringBuilder(key.substring(0, showLength)).append("******")
.append(key.substring(key.length() - showLength)).toString();
}
return null;
}
}
/**
* 两个支付宝客户端,用户可以使用任意一个.
*
* alipay-trade-sdk 是对alipay-sdk-java的封装,建议使用alipay-trade-sdk.
*
* @author mengday zhang
*/
@Configuration
@EnableConfigurationProperties(AlipayProperties.class)
public class AlipayConfiguration {
@Autowired
private AlipayProperties properties;
/**
* alipay-trade-sdk
* @return
*/
@Bean
public AlipayTradeService alipayTradeService() {
return new AlipayTradeServiceImpl.ClientBuilder()
.setGatewayUrl(properties.getGatewayUrl())
.setAppid(properties.getAppid())
.setPrivateKey(properties.getAppPrivateKey())
.setAlipayPublicKey(properties.getAlipayPublicKey())
.setSignType(properties.getSignType())
.build();
}
/**
* alipay-sdk-java
* @return
*/
@Bean
public AlipayClient alipayClient(){
return new DefaultAlipayClient(properties.getGatewayUrl(),
properties.getAppid(),
properties.getAppPrivateKey(),
properties.getFormate(),
properties.getCharset(),
properties.getAlipayPublicKey(),
properties.getSignType());
}
}
/**
* 支付宝-电脑网站支付.
* <p>
* 电脑网站支付 https://docs.open.alipay.com/270/105898/
*
* @author Mengday Zhang
* @version 1.0
* @since 2018/6/14
*/
@Controller
@RequestMapping("/alipay/page")
public class AlipayPagePayController {
@Autowired
private AlipayProperties alipayProperties;
@Autowired
private AlipayClient alipayClient;
@Autowired
private AlipayController alipayController;
@PostMapping("/gotoPayPage")
public void gotoPayPage(HttpServletResponse response) throws AlipayApiException, IOException {
// 订单模型
String productCode = "FAST_INSTANT_TRADE_PAY";
AlipayTradePagePayModel model = new AlipayTradePagePayModel();
model.setOutTradeNo(UUID.randomUUID().toString());
model.setSubject("支付测试");
model.setTotalAmount("0.01");
model.setBody("支付测试,共0.01元");
model.setProductCode(productCode);
AlipayTradePagePayRequest pagePayRequest =new AlipayTradePagePayRequest();
pagePayRequest.setReturnUrl("http://s9v2cw.natappfree.cc/alipay/page/returnUrl");
pagePayRequest.setNotifyUrl(alipayProperties.getNotifyUrl());
pagePayRequest.setBizModel(model);
// 调用SDK生成表单, 并直接将完整的表单html输出到页面
String form = alipayClient.pageExecute(pagePayRequest).getBody();
response.setContentType("text/html;charset=" + alipayProperties.getCharset());
response.getWriter().write(form);
response.getWriter().flush();
response.getWriter().close();
}
@RequestMapping("/returnUrl")
public String returnUrl(HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException, AlipayApiException {
response.setContentType("text/html;charset=" + alipayProperties.getCharset());
boolean verifyResult = alipayController.rsaCheckV1(request);
if(verifyResult){
//验证成功
//请在这里加上商户的业务逻辑程序代码,如保存支付宝交易号
//商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//支付宝交易号
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
return "pagePaySuccess";
}else{
return "pagePayFail";
}
}
}
/**
* 支付宝通用接口.
* <p>
* detailed description
*
* @author Mengday Zhang
* @version 1.0
* @since 2018/6/13
*/
@Slf4j
@RestController
@RequestMapping("/alipay")
public class AlipayController {
@Autowired
private AlipayProperties aliPayProperties;
@Autowired
private AlipayClient alipayClient;
@Autowired
private AlipayTradeService alipayTradeService;
/**
* 支付异步通知
*
* 接收到异步通知并验签通过后,一定要检查通知内容,包括通知中的app_id、out_trade_no、total_amount是否与请求中的一致,并根据trade_status进行后续业务处理。
*
* https://docs.open.alipay.com/194/103296
*/
@RequestMapping("/notify")
public String notify(HttpServletRequest request) throws AlipayApiException, UnsupportedEncodingException {
// 一定要验签,防止黑客篡改参数
Map<String, String[]> parameterMap = request.getParameterMap();
StringBuilder notifyBuild = new StringBuilder("/****************************** alipay notify ******************************/\n");
parameterMap.forEach((key, value) -> notifyBuild.append(key + "=" + value[0] + "\n") );
log.info(notifyBuild.toString());
boolean flag = this.rsaCheckV1(request);
if (flag) {
/**
* TODO 需要严格按照如下描述校验通知数据的正确性
*
* 商户需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号,
* 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),
* 同时需要校验通知中的seller_id(或者seller_email) 是否为out_trade_no这笔单据的对应的操作方(有的时候,一个商户可能有多个seller_id/seller_email),
*
* 上述有任何一个验证不通过,则表明本次通知是异常通知,务必忽略。
* 在上述验证通过后商户必须根据支付宝不同类型的业务通知,正确的进行不同的业务处理,并且过滤重复的通知结果数据。
* 在支付宝的业务通知中,只有交易通知状态为TRADE_SUCCESS或TRADE_FINISHED时,支付宝才会认定为买家付款成功。
*/
//交易状态
String tradeStatus = new String(request.getParameter("trade_status").getBytes("ISO-8859-1"),"UTF-8");
// 商户订单号
String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
//支付宝交易号
String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
//付款金额
String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
// TRADE_FINISHED(表示交易已经成功结束,并不能再对该交易做后续操作);
// TRADE_SUCCESS(表示交易已经成功结束,可以对该交易做后续操作,如:分润、退款等);
if(tradeStatus.equals("TRADE_FINISHED")){
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,
// 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),并执行商户的业务程序
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
//如果有做过处理,不执行商户的业务程序
//注意:
//如果签约的是可退款协议,退款日期超过可退款期限后(如三个月可退款),支付宝系统发送该交易状态通知
//如果没有签约可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
} else if (tradeStatus.equals("TRADE_SUCCESS")){
//判断该笔订单是否在商户网站中已经做过处理
//如果没有做过处理,根据订单号(out_trade_no)在商户网站的订单系统中查到该笔订单的详细,
// 并判断total_amount是否确实为该订单的实际金额(即商户订单创建时的金额),并执行商户的业务程序
//请务必判断请求时的total_fee、seller_id与通知时获取的total_fee、seller_id为一致的
//如果有做过处理,不执行商户的业务程序
//注意:
//如果签约的是可退款协议,那么付款完成后,支付宝系统发送该交易状态通知。
}
return "success";
}
return "fail";
}
/**
* 订单查询(最主要用于查询订单的支付状态)
* @param orderNo 商户订单号
* @return
*/
@GetMapping("/query")
public String query(String orderNo){
AlipayTradeQueryRequestBuilder builder = new AlipayTradeQueryRequestBuilder()
.setOutTradeNo(orderNo);
AlipayF2FQueryResult result = alipayTradeService.queryTradeResult(builder);
switch (result.getTradeStatus()) {
case SUCCESS:
log.info("查询返回该订单支付成功: )");
AlipayTradeQueryResponse resp = result.getResponse();
log.info(resp.getTradeStatus());
// log.info(resp.getFundBillList());
break;
case FAILED:
log.error("查询返回该订单支付失败!!!");
break;
case UNKNOWN:
log.error("系统异常,订单支付状态未知!!!");
break;
default:
log.error("不支持的交易状态,交易返回异常!!!");
break;
}
return result.getResponse().getBody();
}
/**
* 退款
* @param orderNo 商户订单号
* @return
*/
@PostMapping("/refund")
@ResponseBody
public String refund(String orderNo) throws AlipayApiException {
AlipayTradeRefundRequest alipayRequest = new AlipayTradeRefundRequest();
AlipayTradeRefundModel model=new AlipayTradeRefundModel();
// 商户订单号
model.setOutTradeNo(orderNo);
// 退款金额
model.setRefundAmount("0.01");
// 退款原因
model.setRefundReason("无理由退货");
// 退款订单号(同一个订单可以分多次部分退款,当分多次时必传)
// model.setOutRequestNo(UUID.randomUUID().toString());
alipayRequest.setBizModel(model);
AlipayTradeRefundResponse alipayResponse = alipayClient.execute(alipayRequest);
System.out.println(alipayResponse.getBody());
return alipayResponse.getBody();
}
/**
* 退款查询
* @param orderNo 商户订单号
* @param refundOrderNo 请求退款接口时,传入的退款请求号,如果在退款请求时未传入,则该值为创建交易时的外部订单号
* @return
* @throws AlipayApiException
*/
@GetMapping("/refundQuery")
@ResponseBody
public String refundQuery(String orderNo, String refundOrderNo) throws AlipayApiException {
AlipayTradeFastpayRefundQueryRequest alipayRequest = new AlipayTradeFastpayRefundQueryRequest();
AlipayTradeFastpayRefundQueryModel model=new AlipayTradeFastpayRefundQueryModel();
model.setOutTradeNo(orderNo);
model.setOutRequestNo(refundOrderNo);
alipayRequest.setBizModel(model);
AlipayTradeFastpayRefundQueryResponse alipayResponse = alipayClient.execute(alipayRequest);
System.out.println(alipayResponse.getBody());
return alipayResponse.getBody();
}
/**
* 关闭交易
* @param orderNo
* @return
* @throws AlipayApiException
*/
@PostMapping("/close")
@ResponseBody
public String close(String orderNo) throws AlipayApiException {
AlipayTradeCloseRequest alipayRequest = new AlipayTradeCloseRequest();
AlipayTradeCloseModel model =new AlipayTradeCloseModel();
model.setOutTradeNo(orderNo);
alipayRequest.setBizModel(model);
AlipayTradeCloseResponse alipayResponse = alipayClient.execute(alipayRequest);
System.out.println(alipayResponse.getBody());
return alipayResponse.getBody();
}
/**
* 校验签名
* @param request
* @return
*/
public boolean rsaCheckV1(HttpServletRequest request){
// https://docs.open.alipay.com/54/106370
// 获取支付宝POST过来反馈信息
Map<String,String> params = new HashMap<>();
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] + ",";
}
params.put(name, valueStr);
}
try {
boolean verifyResult = AlipaySignature.rsaCheckV1(params,
aliPayProperties.getAlipayPublicKey(),
aliPayProperties.getCharset(),
aliPayProperties.getSignType());
return verifyResult;
} catch (AlipayApiException e) {
log.debug("verify sigin error, exception is:{}", e);
return false;
}
}
}
/**
* WebMVC 配置.
* <p>
* 添加路径和页面的映射关系
*
* @author Mengday Zhang
* @version 1.0
* @since 2018/6/13
*/
@Configuration
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
@Override
protected void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/gotoWapPage").setViewName("gotoWapPay");
registry.addViewController("/gotoPagePage").setViewName("gotoPagePay");
super.addViewControllers(registry);
}
}
gotoPagePay.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body style="font-size: 30px">
<form method="post" action="/alipay/page/gotoPayPage">
<h3>购买商品:越南新娘</h3>
<h3>价格:20000</h3>
<h3>数量:10个</h3>
<button style="width: 100%; height: 60px; alignment: center; background: #b49e8f" type="submit">立即支付</button>
</form>
</body>
</html>
pagePaySuccess.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>电脑网站支付 成功,我们将尽快从越南偷渡过来,收货后请请及时验货!欢迎下次再来</h1>
</body>
</html>
言
本教程详细介绍了如何使用ssm框架实现支付宝支付功能。本文章分为两大部分,分别是「支付宝测试环境代码测试」和「将支付宝支付整合到ssm框架」,详细的代码和图文解释,自己实践的时候一定仔细阅读相关文档,话不多说我们开始。
一、支付宝测试环境代码测试
源代码
https://github.com/OUYANGSIHAI/sihai-maven-ssm-alipay
1、下载电脑网站的官方demo:
下载:https://docs.open.alipay.com/270/106291/
2.下载解压导入eclipse
readme.txt请好好看一下。
只有一个Java配置类,其余都是JSP。
3、配置AlipayConfig
(1) 注册蚂蚁金服开发者账号(免费,不像苹果会收取费用)
注册地址:https://open.alipay.com ,用你的支付宝账号扫码登录,完善个人信息,选择服务类型(我选的是自研)。
(2) 设置app_id和gatewayUrl
其中密钥需要自己生成,appID和支付宝网关是已经给好的,网关有dev字样,表明是用于开发测试。
(3) 设置密钥
点击“生成方法”,打开界面如下:
下周密钥生成工具,解压打开后,选择2048位生成密钥:
如果没有设置过,此时显示文本是"设置应用公钥",我这里是已经设置过得。
设置方法,"打开密钥文件路径":
复制应用公钥2048.txt中的内容到点击"设置应用公钥"的弹出框中,保存:
点击如上图链接,复制弹出框里面的内容到alipay_public_key。
如果这个设置不对,结果是:支付成功,但是验签失败。
如果是正式环境,需要上传到对应的应用中:
(4) 服务器异步通知页面路径(notify_url)
如果没有改名,修改IP和端口号就可以了,我自己的如下:
http://localhost:8080/alipay.trade.page.pay-JAVA-UTF-8/notify_url.jsp
(5) 页面跳转同步通知页面的路径(return_url)
http://localhost:8080/alipay.trade.page.pay-JAVA-UTF-8/return_url.jsp
4、测试运行
测试用的支付宝买家账户可以在"沙箱账"这个页面可以找到:
支付成功后,验签结果:
问题解决
由于我们使用的是沙箱测试环境,测试环境和正式上线的环境的网关是不一样的,如果配置错误,会出现,appid错误的问题。配置如下:
源代码下载
链接: https://pan.baidu.com/s/1n6GbEJiMzoGWJrSw0bb2Cg 密码: zd9e
二、将支付宝支付整合到ssm框架
1、项目架构
整合到ssm一样,我们需要像沙箱测试环境一样,需要修改支付的配置信息
2、数据库代码
主要包括以下的数据库表:
drop table if exists user; /*==============================================================*/ /* Table: user */ /*==============================================================*/ create table user ( id varchar(20) not null, username varchar(128), sex varchar(20), primary key (id) ); alter table user comment '用户表'; CREATE TABLE `flow` ( `id` varchar(20) NOT NULL, `flow_num` varchar(20) DEFAULT NULL COMMENT '流水号', `order_num` varchar(20) DEFAULT NULL COMMENT '订单号', `product_id` varchar(20) DEFAULT NULL COMMENT '产品主键ID', `paid_amount` varchar(11) DEFAULT NULL COMMENT '支付金额', `paid_method` int(11) DEFAULT NULL COMMENT '支付方式 1:支付宝 2:微信', `buy_counts` int(11) DEFAULT NULL COMMENT '购买个数', `create_time` datetime DEFAULT NULL COMMENT '创建时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='流水表'; CREATE TABLE `orders` ( `id` varchar(20) NOT NULL, `order_num` varchar(20) DEFAULT NULL COMMENT '订单号', `order_status` varchar(20) DEFAULT NULL COMMENT '订单状态 10:待付款 20:已付款', `order_amount` varchar(11) DEFAULT NULL COMMENT '订单金额', `paid_amount` varchar(11) DEFAULT NULL COMMENT '实际支付金额', `product_id` varchar(20) DEFAULT NULL COMMENT '产品表外键ID', `buy_counts` int(11) DEFAULT NULL COMMENT '产品购买的个数', `create_time` datetime DEFAULT NULL COMMENT '订单创建时间', `paid_time` datetime DEFAULT NULL COMMENT '支付时间', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表'; CREATE TABLE `product` ( `id` varchar(20) NOT NULL, `name` varchar(20) DEFAULT NULL COMMENT '产品名称', `price` varchar(11) DEFAULT NULL COMMENT '价格', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='产品表 ';
3、dao数据接口层
这里就不介绍了,这个只包括简单的curd,可以使用`通用mapper`,或者`逆向工程`就行。以订单order为例给出:
public interface OrdersMapper { int countByExample(OrdersExample example); int deleteByExample(OrdersExample example); int deleteByPrimaryKey(String id); int insert(Orders record); int insertSelective(Orders record); List<Orders> selectByExample(OrdersExample example); Orders selectByPrimaryKey(String id); int updateByExampleSelective(@Param("record") Orders record, @Param("example") OrdersExample example); int updateByExample(@Param("record") Orders record, @Param("example") OrdersExample example); int updateByPrimaryKeySelective(Orders record); int updateByPrimaryKey(Orders record); }
注意:源代码最后给出
4、service层
同上,最后在项目源代码里可见。以订单order为例给出:
/** * 订单操作 service * @author ibm * */ public interface OrdersService { /** * 新增订单 * @param order */ public void saveOrder(Orders order); /** * * @Title: OrdersService.java * @Package com.sihai.service * @Description: 修改叮当状态,改为 支付成功,已付款; 同时新增支付流水 * Copyright: Copyright (c) 2017 * Company:FURUIBOKE.SCIENCE.AND.TECHNOLOGY * * @author sihai * @date 2017年8月23日 下午9:04:35 * @version V1.0 */ public void updateOrderStatus(String orderId, String alpayFlowNum, String paidAmount); /** * 获取订单 * @param orderId * @return */ public Orders getOrderById(String orderId); }
三、支付宝支付controller(支付流程)
支付流程图
首先,启动项目后,输入http://localhost:8080/,会进入到商品页面,如下:
下面是页面代码
商品页面(products.jsp)
代码实现:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %> <script src="<%=request.getContextPath() %>/static/js/jquery.min.js" type="text/javascript"></script> <html> <head> </head> <body> <table> <tr> <td> 产品编号 </td> <td> 产品名称 </td> <td> 产品价格 </td> <td> 操作 </td> </tr> <c:forEach items="${pList }" var="p"> <tr> <td> ${p.id } </td> <td> ${p.name } </td> <td> ${p.price } </td> <td> <a href="<%=request.getContextPath() %>/alipay/goConfirm.action?productId=${p.id }">购买</a> </td> </tr> </c:forEach> </table> <input type="hidden" id="hdnContextPath" name="hdnContextPath" value="<%=request.getContextPath() %>"/> </body> </html> <script type="text/javascript"> $(document).ready(function() { var hdnContextPath = $("#hdnContextPath").val(); }); </script>
点击上面的购买,进入到订单页面
填写个数,然后点击生成订单,调用如下代码
根据SID(生成id的工具)等信息生成订单,保存到数据库。
进入到选择支付页面
调用了如下代码:
然后,我们选择支付宝支付,进入到了我们支付的页面了,大功告成!
调用了如下代码:
/** * * @Title: AlipayController.java * @Package com.sihai.controller * @Description: 前往支付宝第三方网关进行支付 * Copyright: Copyright (c) 2017 * Company:FURUIBOKE.SCIENCE.AND.TECHNOLOGY * * @author sihai * @date 2017年8月23日 下午8:50:43 * @version V1.0 */ @RequestMapping(value = "/goAlipay", produces = "text/html; charset=UTF-8") @ResponseBody public String goAlipay(String orderId, HttpServletRequest request, HttpServletRequest response) throws Exception { Orders order = orderService.getOrderById(orderId); Product product = productService.getProductById(order.getProductId()); //获得初始化的AlipayClient AlipayClient alipayClient = new DefaultAlipayClient(AlipayConfig.gatewayUrl, AlipayConfig.app_id, AlipayConfig.merchant_private_key, "json", AlipayConfig.charset, AlipayConfig.alipay_public_key, AlipayConfig.sign_type); //设置请求参数 AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest(); alipayRequest.setReturnUrl(AlipayConfig.return_url); alipayRequest.setNotifyUrl(AlipayConfig.notify_url); //商户订单号,商户网站订单系统中唯一订单号,必填 String out_trade_no = orderId; //付款金额,必填 String total_amount = order.getOrderAmount(); //订单名称,必填 String subject = product.getName(); //商品描述,可空 String body = "用户订购商品个数:" + order.getBuyCounts(); // 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。该参数数值不接受小数点, 如 1.5h,可转换为 90m。 String timeout_express = "1c"; alipayRequest.setBizContent("{"out_trade_no":""+ out_trade_no +""," + ""total_amount":""+ total_amount +""," + ""subject":""+ subject +""," + ""body":""+ body +""," + ""timeout_express":""+ timeout_express +""," + ""product_code":"FAST_INSTANT_TRADE_PAY"}"); //请求 String result = alipayClient.pageExecute(alipayRequest).getBody(); return result; }
这段代码都可以在阿里支付的demo里面找到的,只需要复制过来,然后改改,整合到ssm环境即可。
上面就是将阿里支付宝支付整合到ssm的全过程了。
*请认真填写需求信息,我们会在24小时内与您取得联系。