网站怎么接入微信扫码支付?
参考资料:产品中心 - 微信支付商户平台 (qq.com)
付款码支付、JSAPI支付、小程序支付、Native支付、APP支付、刷脸支付
1.1、付款码支付用户展示微信钱包内的“付款码”给商家,商家扫描后直接完成支付,适用于线下面对面收银的场景。
1.2、JSAPI支付线下场所:商户展示一个支付二维码,用户使用微信扫描二维码后,输入需要支付的金额,完成支付。公众号场景:用户在微信内进入商家公众号,打开某个页面,选择某个产品,完成支付。PC网站场景:在网站中展示二维码,用户使用微信扫描二维码,输入需要支付的金额,完成支付。特点:用户在客户端输入支付金额
1.3、小程序支付在微信小程序平台内实现支付的功能。
1.4、Native支付Native支付是指商户展示支付二维码,用户再用微信“扫一扫”完成支付的模式。这种方式适用于PC网站。
特点:商家预先指定支付金额
1.5、APP支付商户通过在移动端独立的APP应用程序中集成微信支付模块,完成支付。
1.6、刷脸支付用户在刷脸设备前通过摄像头刷脸、识别身份后进行的一种支付方式。
2、接口版本微信支付企业主流的API版本有v2和v3,课程中我们使用微信支付APIv3。
V2和V3的比较
相比较而言,APIv2比APIv3安全性更高,但是APIv2中有一些功能在APIv3中尚未完整实现,具体参考如下API字典页面:API字典概览 | 微信支付商户平台文档中心 (qq.com)
3、接入指引3.1、获取开发参数如果需要独立申请和开通微信支付功能,可以参考如下官方文档。开通微信支付后,才能获取相关的开发参数以及商户公钥和商户私钥文件。
参考资料:微信支付接入指引 - 微信支付商户平台 (qq.com)
3.2、配置开发参数在service-order服务的resources目录中创建wxpay.properties
这个文件定义了在“接入指引”的步骤中我们提前准备的微信支付相关的参数,例如商户号、APPID、API秘钥等等
# 微信支付相关参数wxpay: mch-id: 1558950191 #商户号 mch-serial-no: 34345964330B66427E0D3D28826C4993C77E631F # 商户API证书序列号 private-key-path: D:/project/yygh/cert/apiclient_key.pem # 商户私钥文件 api-v3-key: UDuLFDcmy5Eb6o0nTNZdu6ek4DDh4K8B # APIv3密钥 appid: wx74862e0dfcf69954 # APPID notify-url: https://7d92-115-171-63-135.ngrok.io/api/order/wxpay/payment/notify # 接收支付结果通知地址 notify-refund-url: http://agxnyzl04y90.ngrok.xiaomiqiu123.top/api/order/wxpay/refunds/notify # 接收退款结果通知地址3.3、复制商户私钥将商户私钥文件复制到配置文件指定的目录下:
资料:资料>微信支付>商户证书>apiclient_key.pem
private-key-path: D:/project/yygh/cert/apiclient_key.pem # 商户私钥文件3.4、证书密钥使用说明(了解)参考文档:APIv3证书与密钥使用说明
一个完整的请求和响应的流程:
商户使用商户私钥对请求进行签名,发送给微信支付平台,平台使用商户公钥进行签名验证。微信支付平台使用平台私钥对响应进行签名,商户使用微信支付平台公钥对响应进行验签。第02章-订单支付1、微信支付平台证书的获取1.1、引入SDK参考文档:SDK&工具
我们可以使用官方提供的 SDK wechatpay-java
在service-order微服务中添加依赖:
com.github.wechatpay-apiv3 wechatpay-java 0.2.61.2、读取支付参数在config 包中 创建 WxPayConfig.java
package com.atguigu.syt.order.config;@Configuration@PropertySource("classpath:wxpay.properties") //读取配置文件@ConfigurationProperties(prefix="wxpay") //读取wxpay节点@Datapublic class WxPayConfig { // 商户号 private String mchId; // 商户API证书序列号 private String mchSerialNo; // 商户私钥文件 private String privateKeyPath; // APIv3密钥 private String apiV3Key; // APPID private String appid; // 接收支付结果通知地址 private String notifyUrl; // 接收退款结果通知地址 private String notifyRefundUrl; }1.3、自动更新微信支付平台证书在 API 请求过程中,客户端需使用微信支付平台证书,验证服务器应答的真实性和完整性。我们使用自动更新平台证书的配置类 RSAAutoCertificateConfig。每个商户号只能创建一个 RSAAutoCertificateConfig。
在WxPayConfig中添加如下方法:
/** * 获取微信支付配置对象 * @return */@Beanpublic RSAAutoCertificateConfig getConfig(){ return new RSAAutoCertificateConfig.Builder() .merchantId(mchId) .privateKeyFromPath(privateKeyPath) .merchantSerialNumber(mchSerialNo) .apiV3Key(apiV3Key) .build();}RSAAutoCertificateConfig 通过 RSAAutoCertificateProvider 自动下载微信支付平台证书。 同时,RSAAutoCertificateProvider 会启动一个后台线程,定时更新证书(目前设计为60分钟),以实现证书过期时的新老证书平滑切换。
常见错误:引入商户私钥后如果项目无法启动,则需要升级JDK版本,并重新配置idea编译和运行环境到最新版本的JDK。建议升级到1.8.0_300以上
2、生成支付二维码2.1、Native支付流程参考文档:业务流程时序图
2.2、Controller在service-order中创建FrontWXPayController
package com.atguigu.syt.order.controller.front;@Api(tags = "微信支付接口")@RestController@RequestMapping("/front/order/wxpay")public class FrontWXPayController { @Resource private WxPayService wxPayService; @Resource private AuthContextHolder authContextHolder; @ApiOperation("获取支付二维码url") @ApiImplicitParam(name = "outTradeNo",value = "订单号", required = true) @GetMapping("/auth/nativePay/{outTradeNo}") public Result nativePay(@PathVariable String outTradeNo, HttpServletRequest request, HttpServletResponse response) { //校验用户登录状态 authContextHolder.checkAuth(request, response); String codeUrl = wxPayService.createNative(outTradeNo); return Result.ok(codeUrl); }}2.3、ServiceSDK参考代码:wechatpay-java/NativePayServiceExample.java at main · wechatpay-apiv3/wechatpay-java · GitHub
具体代码示例如下:
Native下单API参数参考:Native下单API
接口:OrderInfoService
/** * 根据订单号获取订单 * @param outTradeNo * @return */OrderInfo selectByOutTradeNo(String outTradeNo);实现:OrderInfoServiceImpl
@Overridepublic OrderInfo selectByOutTradeNo(String outTradeNo) { LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper(); queryWrapper.eq(OrderInfo::getOutTradeNo, outTradeNo); return baseMapper.selectOne(queryWrapper);}接口:WxPayService
package com.atguigu.syt.order.service;public interface WxPayService { /** * 获取支付二维码utl * @param outTradeNo * @return */ String createNative(String outTradeNo);}实现:WxPayServiceImpl
package com.atguigu.syt.order.service.impl;@Service@Slf4jpublic class WxPayServiceImpl implements WxPayService { @Resource private RSAAutoCertificateConfig rsaAutoCertificateConfig; @Resource private WxPayConfig wxPayConfig; @Resource private OrderInfoService orderInfoService; @Override public String createNative(String outTradeNo) { // 初始化服务 NativePayService service = new NativePayService.Builder().config(rsaAutoCertificateConfig).build(); // 调用接口 try { //获取订单 OrderInfo orderInfo = orderInfoService.selectByOutTradeNo(outTradeNo); PrepayRequest request = new PrepayRequest(); // 调用request.setXxx(val)设置所需参数,具体参数可见Request定义 request.setAppid(wxPayConfig.getAppid()); request.setMchid(wxPayConfig.getMchId()); request.setDescription(orderInfo.getTitle()); request.setOutTradeNo(outTradeNo); request.setNotifyUrl(wxPayConfig.getNotifyUrl()); Amount amount = new Amount(); //amount.setTotal(orderInfo.getAmount().multiply(new BigDecimal(100)).intValue()); amount.setTotal(1);//1分钱 request.setAmount(amount); // 调用接口 PrepayResponse prepayResponse = service.prepay(request); return prepayResponse.getCodeUrl(); } catch (HttpException e) { // 发送HTTP请求失败 // 调用e.getHttpRequest()获取请求打印日志或上报监控,