项目初始化

使用 Spring Initializer 进行项目初始化, 记得后面选上 lombok、spring web、mybatis、mysql driver

在 application.yml 中对数据库连接进行配置:

spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost/mall?characterEncoding=utf-8&useSSL=false&serverTimezone=UTCusername: rootpassword: 123456

对接微信Native支付

1、引入作者的maven支付包

<dependency><groupId>cn.springboot</groupId><artifactId>best-pay-sdk</artifactId><version>1.3.0</version>
</dependency>

2、编写接口

package com.imooc.pay.service;import com.lly835.bestpay.model.PayResponse;import java.math.BigDecimal;public interface IPayService {/*** 创建/发起字符*/PayResponse create(String orderId, BigDecimal amount);
}

3、编写实现类

package com.imooc.pay.service.impl;import com.imooc.pay.service.IPayService;
import com.lly835.bestpay.config.WxPayConfig;
import com.lly835.bestpay.enums.BestPayTypeEnum;
import com.lly835.bestpay.model.PayRequest;
import com.lly835.bestpay.model.PayResponse;
import com.lly835.bestpay.service.impl.BestPayServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;import javax.xml.ws.Response;
import java.math.BigDecimal;@Slf4j
@Service
public class PayService implements IPayService {/**** @param orderId* @param amount*/@Overridepublic PayResponse create(String orderId, BigDecimal amount) {WxPayConfig wxPayConfig =  new WxPayConfig();wxPayConfig.setAppId("wxd898fcb01713c658");  //设置AppIdwxPayConfig.setMchId("1483469312");  //设置商户IdwxPayConfig.setMchKey("7mdApPMfXddfWWbbP4DUaVYm2wjyh3v3"); //设置商户密钥wxPayConfig.setNotifyUrl("http://localhost");BestPayServiceImpl bestPayService = new BestPayServiceImpl();bestPayService.setWxPayConfig(wxPayConfig);PayRequest request = new PayRequest();request.setOrderName("9442081-支付测试");request.setOrderId(orderId);request.setOrderAmount(amount.doubleValue());request.setPayTypeEnum(BestPayTypeEnum.WXPAY_NATIVE);PayResponse response = bestPayService.pay(request);log.info("response={}", response);return response;}
}

4、编写测试代码

package com.imooc.pay.service.impl;import com.imooc.pay.PayApplication;
import com.imooc.pay.PayApplicationTests;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;import java.math.BigDecimal;import static org.junit.Assert.*;public class PayServiceTest extends PayApplicationTests {@Autowiredprivate PayService payService;@Testpublic void create() {payService.create("chenxin123456", BigDecimal.valueOf(0.01));}
}

运行结果:

红线的部分生成二维码就可以完成支付!!

使用程序实现将支付链路转换为二维码

1、引入 spring-boot-starter-freemarker 依赖

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

2、编写controller类

package com.imooc.pay.controller;import com.imooc.pay.service.impl.PayService;
import com.lly835.bestpay.model.PayResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;@Controller
@RequestMapping("/pay")
public class PayController {@Autowiredprivate PayService payService;@GetMapping("/create")public ModelAndView create(@RequestParam("orderId") String orderId,@RequestParam("amount") BigDecimal amount) {PayResponse response = payService.create(orderId, amount);Map map = new HashMap<>();map.put("codeUrl", response.getCodeUrl());return new ModelAndView("create", map);}
}

3、在templates下编写create.ftl。两端 jquery 代码是从 https://www.bootcdn.cn/ 中拷贝的。qrcode可以将一段字符串变成一张二维码来进行显示。

<html><head><meta charset="utf-8"><title>支付</title></head><body><div id="myQrcode"></div><script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.5.1/jquery.min.js"></script><script src="https://cdn.bootcdn.net/ajax/libs/jquery.qrcode/1.0/jquery.qrcode.min.js"></script><script>jQuery('#myQrcode').qrcode({text:"${codeUrl}"});</script></body></html>

微信异步通知

  • notify_url 要在微信后台设置吗?
  • notify_url 一定要用域名吗?

1、在 NATAPP.cn 网站购买一个隧道,可以将127.0.0.1映射到公网,启动下载的natapp.exe可获得一个公网地址:

2、更改NotifyUrl的值:

wxPayConfig.setNotifyUrl("http://xiaoxin-mall.natapp1.cc/pay/notify");

3、在PayController.java中编写方法:

@PostMapping("/notify")
public void asyncNotify(@RequestBody String notifyData) {log.info("notifyData={}", notifyData);
}

4、支付一笔订单,可以发现,在控制台,可以收到多次重复的返回信息。

5、现在我们收到返回信息后在本地进行验证,并将验证成功地消息返回微信,这样微信就不会再给我们发信息了。

PayService.java:

/*** 异步通知处理* @param notifyData*/
@Override
public String asyncNotify(String notifyData) {//1、签名校验PayResponse payResponse = bestPayService.asyncNotify(notifyData);log.info("payResponse = {}", payResponse);//2、金额校验(从数据库查订单)//3、修改订单支付状态//4、告诉微信我已经收到return "<xml>\n" +"   <return_code><![CDATA[SUCCESS]]></return_code>\n" +"   <return_msg><![CDATA[OK]]></return_msg>\n" +"</xml>";
}

PayController.java:

@PostMapping("/notify")
@ResponseBody
public String asyncNotify(@RequestBody String notifyData) {log.info("notifyData={}", notifyData);return payService.asyncNotify(notifyData);
}

支付宝支付

1、支付宝密钥说明

  • 一共涉及到4个密钥,分别是:商户应用公钥、商户应用私钥、支付宝公钥、支付宝私钥。
  • 用户在本地生成商户应用公钥和商户应用私钥,然后将商户应用公钥与支付宝公钥进行绑定,支付宝的私钥存储在支付宝的后台,这个用户看不到。
  • 发起支付:商户(商户应用私钥签名)—> 支付宝(商户应用公钥验签)
  • 异步通知:支付宝(支付宝私钥签名)----> 商户(支付宝公钥验签)
  • 注意:RSA签名不等于RAS加密。签名和加密的代码是不一样的。

2、编写代码,加入支付宝支付

接口IPayService:

public interface IPayService {/*** 创建/发起支付*/PayResponse create(String orderId, BigDecimal amount, BestPayTypeEnum bestPayTypeEnum);/*** 异步通知处理*/String asyncNotify(String notifyData);
}

BestPayConfig.java:

@Component
public class BestPayConfig {@Beanpublic BestPayService bestPayService() {//微信支付配置WxPayConfig wxPayConfig =  new WxPayConfig();wxPayConfig.setAppId("wxd898fcb01713c658");  //设置AppIdwxPayConfig.setMchId("1483469312");  //设置商户IdwxPayConfig.setMchKey("7mdApPMfXddfWWbbP4DUaVYm2wjyh3v3"); //设置商户密钥wxPayConfig.setNotifyUrl("http://xiaoxin-mall.natapp1.cc/pay/notify");//支付宝配置AliPayConfig aliPayConfig = new AliPayConfig();aliPayConfig.setAppId("2018062960540016");aliPayConfig.setPrivateKey("MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDUcbUUBaTJA4ngFx1xED2WHrkS4YCi3BRDPu/qU+MXj7VNy/ip+VKSK9aGPd2dRswkt/4DOoOxnnesJDcve+2W9y2gPoOdSVjGlEwTE6MqeB5f3l+RO9Kcb2zL4JwCRxlE0HHLeRdWtnmbelh1rg8zTFwGnoi1pbQajAT/FGDFqIpdI6FrEYbyeR/VNxFXIGK16Z7gfnWRnS4TP93O5ckcuaAcE8tqW16G7u41bKsnsv2149mucBM2hFSEVD/KcGYYke3pD7VpQdk0+WhxITSsa5I8DfSFRKokN7iJoKjYWjI4gN3fxFWLbymeIumoOWdJflwYI5oL+GdVIHfQ0ETLAgMBAAECggEBALaqurdnjuQkfcXIOlGAVGQjMKFycmgWcfnMQQAsdyRINe2Zx8tnDL+QoBm3UjmsqVWdOvVNt/TevCmwzh6vIYBgMsQJXKO+cG33D16L0Q1wUTW/gE7hsFtAV70J+TrgJXMNA/ufuBigN/oe/bbaHknOi4ZJhGUkALOe16D4xajNjHcYdvkfw5Zkv9nAt+GjFphe1lt35KIx6ahFzMcnzzHYy4ezDFdQWPkT7CqrL8Nh9KPm6Sjbzw2JP3RH91OU1q44gPj7yyLTs1oxt4gEqOgVnczJWXoH+eKRmxRoIvodnB4kf1W9LTzAc4Qs7OneDccvhrOoTD3MGhqW0poXZFkCgYEA6dxBCLnU5oeoctoltnh42DXCzEv/M/gkv9HMY/FFnuM6e0qU5EcFjQtTPRRW1S45ctZaHHhpGppHF7RG+okdALj4x2OC1NG9DL4HboVW3CJ4TzmEeZRkR+LWRWw7FA8eXefDBTC4ojAwqkmbvYP3dm6FjSfNBGYs43Wm6qKTcB0CgYEA6I5rPmAv6rB1BBXF8riNhuoDntbHFHOC9kCwuVJooDBBnxXNCqA9mTdnwE8hjgCgbO5lQkeeIRYiZwFYdCLPW78j6Np5CaX0/ZxcVSUQBFYc3d0e3po+rqpX6BGOj7qGhzDXvAs+HScu7ERy0Kbq6b/EbuLlR3oCKIGncGIaxAcCgYBJyWrjm+6mxgrKIjZf+mb2oQ/Tce8VsKe3tjRtHEVBOqTLHd8Yn6gKtpYO4Yn8PVd2+lb4QK247RCdVA5JIlX6UmJ8VtOC3qJtkM+7eWrMjjuzk4xO6Bkz7Uh6IwoI7DRCoMuRqau30MiqEguHoknEHl8ZCIPRbYOgSRDfW2h1qQKBgF9ODnFPphN+IVZ9PdRNAeMqgDVWO9wLwr38oPAx76LGY/44RwF1zgi+hgxv4YZ6h0RdJq5U/1773TltebyOj4BAAw1oi3YCxzYwID7co4XDbK0X85CykcGvGbuHhm8st/krcR4lVV1JM5esLYmI/nixGGWBIwl53OyQxffunJ19AoGBAOX9cBWFIWh5EHVXYvW90HRBQoo1AYtsdrxTedqrij6cWQms6ACeQZPd5O0V6/Lhz3Lw5NRnUl9MbzwOC7BBSBvhWwNzBOzFnaoOvBABa5nFZsdF5jSI3LJHbnxmMvxnKjCgogSGf+hfgR042b/WKDDBEA965MQJ59tCVhALD81z");aliPayConfig.setAliPayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtojdtkETo4OEsQLeyyPwtWK9ZqYJANq6jjXC74vk9n/r88yW577y7VdxcK9X/F/wvR7D8of7lndYdhg6xZro0eO2skPZTU+A549J7tfzahVbIBAS+x1WPFJwPtVrfBBvkwHL8PT+YnMcxKyBxOa6wo8fzJs1NgU1+qnDCpwUFyv59GUfdzBvTPL1fY3ZzvRHFHbapevVltbO/jNV0thb8dafmcJXl8lnjQy3XlH3eTH28tlVfqickacfRl/WSD8WN3dGgF7dTDKYfSR7YB7jsHe6VzoHM3UnD9/yQbi/Z3ZrL7yOxEjq4tfrKlZIW7ZCoUpOU4QdPIRhLeC6nWyGrQIDAQAB");aliPayConfig.setNotifyUrl("http://xiaoxin-mall.natapp1.cc/pay/notify");aliPayConfig.setReturnUrl("http://127.0.0.1");BestPayServiceImpl bestPayService = new BestPayServiceImpl();bestPayService.setWxPayConfig(wxPayConfig);bestPayService.setAliPayConfig(aliPayConfig);return bestPayService;}
}

PayService.java:

@Slf4j
@Service
public class PayService implements IPayService {@Autowiredprivate BestPayService bestPayService;/**** @param orderId* @param amount*/@Overridepublic PayResponse create(String orderId, BigDecimal amount, BestPayTypeEnum bestPayTypeEnum) {PayRequest request = new PayRequest();request.setOrderName("9442081-支付测试");request.setOrderId(orderId);request.setOrderAmount(amount.doubleValue());request.setPayTypeEnum(bestPayTypeEnum);PayResponse response = bestPayService.pay(request);log.info("response={}", response);return response;}/*** 异步通知处理* @param notifyData*/@Overridepublic String asyncNotify(String notifyData) {//1、签名校验PayResponse payResponse = bestPayService.asyncNotify(notifyData);log.info("payResponse = {}", payResponse);//2、金额校验(从数据库查订单)//3、修改订单支付状态//4、告诉微信我已经收到if(payResponse.getPayPlatformEnum() == BestPayPlatformEnum.WX) {return "<xml>\n" +"   <return_code><![CDATA[SUCCESS]]></return_code>\n" +"   <return_msg><![CDATA[OK]]></return_msg>\n" +"</xml>";} else if(payResponse.getPayPlatformEnum() == BestPayPlatformEnum.ALIPAY)return "success";throw new RuntimeException("异步通知中错误的支付平台");}
}

PayController.java:

@Controller
@RequestMapping("/pay")
@Slf4j
public class PayController {@Autowiredprivate PayService payService;@GetMapping("/create")public ModelAndView create(@RequestParam("orderId") String orderId,@RequestParam("amount") BigDecimal amount,@RequestParam("payType") BestPayTypeEnum bestPayTypeEnum) {PayResponse response = payService.create(orderId, amount, bestPayTypeEnum);//支付方式不同,渲染就不同,WXPAY_NATIVE使用codeUrl,ALIPAY_PC使用bodyMap<String, String> map = new HashMap<>();if(bestPayTypeEnum == BestPayTypeEnum.WXPAY_NATIVE) {map.put("codeUrl", response.getCodeUrl());return new ModelAndView("createForWxNative", map);} else if(bestPayTypeEnum == BestPayTypeEnum.ALIPAY_PC) {map.put("body", response.getBody());return new ModelAndView("createForAlipayPC", map);}throw new RuntimeException("暂不支持的支付类型");}@PostMapping("/notify")@ResponseBodypublic String asyncNotify(@RequestBody String notifyData) {log.info("notifyData={}", notifyData);return payService.asyncNotify(notifyData);}
}

createForAlipayPC.ftl:

<html>
<head><meta charset="utf-8"><title>支付</title>
</head><body>
${body}
</body></html>

支付项目:5、通用型支付系统(1)相关推荐

  1. 微信支付项目四:微信支付笔记

    1. 微信支付项目四:微信支付交付 文章目录 1. 微信支付项目四:微信支付交付 1.1. 微信支付交付方式 1.2. 互联网架构知识时序图 1.3. 微信支付模式二的时序图 1.4. 微信支付订单接 ...

  2. 支付项目:4、支付术语初体验

    如何学好支付 熟悉理论 官方文档 支付资质 企业 本课程提供,与慕课网账号绑定!! 支付场景 1.微信 付款码支付:商户收银员用扫码设备扫描用户的条码/二维码,商户收银系统提交支付. JSAPI支付: ...

  3. 国家重点研发计划“通用三维CAD系统软件产品”项目 正式启动

    2021年3月25日,数码大方(CAXA)牵头承担的2020国家重点研发计划"通用三维CAD系统软件产品"项目启动会在京召开.科技部项目专家.项目牵头单位及参与单位等共同参加了项目 ...

  4. 通用的支付系统该如何设计?

    往期热门文章:1.Java 17 用户采用率在一年内增长了 430% 2.一个中文害我加了两天班 3.微软 Bing 突然爆炸级更新!无需等待人人可用,答案图文并茂,网友:逼 ChatGPT 放大招? ...

  5. 通用数字支付网络(UDPN)于达沃斯论坛期间正式发布

    2023年1月19日,在瑞士达沃斯举行的世界经济论坛 (WEF) 会议期间,通用数字支付网络 (Universal Digital Payment Network, UDPN)正式对外发布. 近年来, ...

  6. 使软件可二次开发_九思软件:平台型OA系统为何要好于项目型OA系统?

    现代企业往往会把企业战略落实在项目中,所以在OA系统选型中很多企业过于侧重项目管理,选择项目型OA办公系统.然而,随着信息化的发展,传统的OA产品已无法满足于企业不断拓展的个性化需求,针对客户需求定制 ...

  7. 支付核心研发部 | POS支付系统技术架构解密

    点击「京东金融技术说」可快速关注 「团队介绍」 POS支付团队,支撑整个京东货到付款业务,配送小哥人手一台POS机就是我们支付工具,为京东数万台POS机提供更好的支付体验.更好的支付产品,是我们整个团 ...

  8. 【闪聚支付项目】项目总结

    目录 1 闪聚支付是个什么样的项目? 1.1 项目背景 1.2 项目的功能模块 2 项目采用什么技术架构? 2.1 微服务技术栈 2.2 接口定义规范 2.3 Swagger如何使用? 2.4 注册中 ...

  9. 闪聚支付项目-项目总结

    闪聚支付是个什么样的项目? 项目背景 随着移动支付的盛行,商业银行.第三方支付公司.其它清算机构.消费金融公司等众多类型的机构,都在为商户提供网络(移动)支付解决方案.另一方面,用户的支付需求繁多,支 ...

最新文章

  1. linux进程的地址空间
  2. ssh配置文件ssh_config和sshd_config区别
  3. 基于kNN的手写字体识别——《机器学习实战》笔记
  4. liigo:爱可视70平板电脑使用感受,遗憾与满足并存
  5. Flask爱家租房--房屋管理(获取房东发布的房源信息条目)
  6. 程序观点下的线性代数
  7. php hibernate,Hibernate总结
  8. JavaScript-作用域和作用域链
  9. 《那些事之Log4j》什么是log4j?【专题一】
  10. 资产负债表 公式总结
  11. 西安电子科技大学出版社 线性代数 参考答案 刘三阳
  12. win7网络适配器_win7网络重置
  13. YOLO多线程多模型运行模式的实施
  14. linux远程主机拒绝连接,linux – Telnet [无法连接到远程主机:拒绝连接]
  15. 【RPA自动化|提升办公效率】无需代码的傻瓜式爬虫
  16. Python+Excel 华尔街的一股清流
  17. libreoffice python_如何在LibreOffice中运行python宏?
  18. java做五子棋 视频_java swing实现五子棋小游戏项目源码附带视频指导运行教程...
  19. 纷享销客显示无法连接服务器,纷享销客
  20. itu ftp address

热门文章

  1. 游戏中的显示器选项的acm
  2. win7+VS2008 System.Runtime.InteropServices.COMException
  3. 全国互联电网调度管理规程(第一章__第九章)
  4. 应用统计学与R语言实现学习笔记(三)——描述性统计
  5. IntelliJ IDEA 2019 激活注册码
  6. Android车载应用开发与分析(13)- 系统设置-蓝牙设置
  7. Linux-如何查看进程和关闭进程
  8. Java解析魔兽争霸3录像W3G文件(三):解析游戏开始前的信息
  9. JavaScript实现11位手机号码正则表达式
  10. vanilla_使用Vanilla JavaScript构建Cookie库