微信支付

This commit is contained in:
zhujj 2019-01-24 11:43:55 +08:00
parent 50c238b1d8
commit 9063795784
9 changed files with 801 additions and 1 deletions

View File

@ -20,11 +20,19 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--企业微信-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-cp</artifactId>
<version>${weixin-java-cp.version}</version>
</dependency>
<!--微信支付-->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-pay</artifactId>
<version>3.3.0</version>
</dependency>
<!-- 通用工具-->
<dependency>
<groupId>com.ruoyi</groupId>
@ -37,6 +45,11 @@
<version>1.16.20</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>1.5.19</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,15 @@
package com.ruoyi.wx.pay;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author Binary Wang
*/
@SpringBootApplication
public class WxPayDemoApplication {
public static void main(String[] args) {
SpringApplication.run(WxPayDemoApplication.class, args);
}
}

View File

@ -0,0 +1,48 @@
package com.ruoyi.wx.pay.config;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
/**
* @author Binary Wang
*/
@Configuration
@ConditionalOnClass(WxPayService.class)
@EnableConfigurationProperties(WxPayProperties.class)
public class WxPayConfiguration {
private WxPayProperties properties;
@Autowired
public WxPayConfiguration(WxPayProperties properties) {
this.properties = properties;
}
@Bean
@ConditionalOnMissingBean
public WxPayService wxService() {
WxPayConfig payConfig = new WxPayConfig();
payConfig.setAppId(StringUtils.trimToNull(this.properties.getAppId()));
payConfig.setMchId(StringUtils.trimToNull(this.properties.getMchId()));
payConfig.setMchKey(StringUtils.trimToNull(this.properties.getMchKey()));
payConfig.setSubAppId(StringUtils.trimToNull(this.properties.getSubAppId()));
payConfig.setSubMchId(StringUtils.trimToNull(this.properties.getSubMchId()));
payConfig.setKeyPath(StringUtils.trimToNull(this.properties.getKeyPath()));
// 可以指定是否使用沙箱环境
payConfig.setUseSandboxEnv(false);
WxPayService wxPayService = new WxPayServiceImpl();
wxPayService.setConfig(payConfig);
return wxPayService;
}
}

View File

@ -0,0 +1,97 @@
package com.ruoyi.wx.pay.config;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
import org.springframework.boot.context.properties.ConfigurationProperties;
/**
* wxpay pay properties
*
* @author Binary Wang
*/
@ConfigurationProperties(prefix = "wechat.pay")
public class WxPayProperties {
/**
* 设置微信公众号或者小程序等的appid
*/
private String appId;
/**
* 微信支付商户号
*/
private String mchId;
/**
* 微信支付商户密钥
*/
private String mchKey;
/**
* 服务商模式下的子商户公众账号ID普通模式请不要配置请在配置文件中将对应项删除
*/
private String subAppId;
/**
* 服务商模式下的子商户号普通模式请不要配置最好是请在配置文件中将对应项删除
*/
private String subMchId;
/**
* apiclient_cert.p12文件的绝对路径或者如果放在项目中请以classpath:开头指定
*/
private String keyPath;
public String getAppId() {
return this.appId;
}
public void setAppId(String appId) {
this.appId = appId;
}
public String getMchId() {
return mchId;
}
public void setMchId(String mchId) {
this.mchId = mchId;
}
public String getMchKey() {
return mchKey;
}
public void setMchKey(String mchKey) {
this.mchKey = mchKey;
}
public String getSubAppId() {
return subAppId;
}
public void setSubAppId(String subAppId) {
this.subAppId = subAppId;
}
public String getSubMchId() {
return subMchId;
}
public void setSubMchId(String subMchId) {
this.subMchId = subMchId;
}
public String getKeyPath() {
return this.keyPath;
}
public void setKeyPath(String keyPath) {
this.keyPath = keyPath;
}
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this,
ToStringStyle.MULTI_LINE_STYLE);
}
}

View File

@ -0,0 +1,138 @@
package com.ruoyi.wx.pay.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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 com.github.binarywang.wxpay.bean.entpay.EntPayBankQueryResult;
import com.github.binarywang.wxpay.bean.entpay.EntPayBankRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayBankResult;
import com.github.binarywang.wxpay.bean.entpay.EntPayQueryResult;
import com.github.binarywang.wxpay.bean.entpay.EntPayRequest;
import com.github.binarywang.wxpay.bean.entpay.EntPayResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/**
* <pre>
* 企业付款相关接口
* Created by Binary Wang on 2018/9/27.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Api("企业付款")
@RequestMapping("/pay")
@RestController
public class EntPayController {
private WxPayService wxService;
@Autowired
public EntPayController(WxPayService wxService) {
this.wxService = wxService;
}
/**
* <pre>
* 企业付款业务是基于微信支付商户平台的资金管理能力为了协助商户方便地实现企业向个人付款针对部分有开发能力的商户提供通过API完成企业付款的功能
* 比如目前的保险行业向客户退保给付理赔
* 企业付款将使用商户的可用余额需确保可用余额充足查看可用余额充值提现请登录商户平台资金管理https://pay.weixin.qq.com/进行操作
* 注意与商户微信支付收款资金并非同一账户需要单独充值
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2
* 接口链接https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers
* </pre>
*
* @param request 请求对象
*/
@ApiOperation(value = "企业付款到零钱")
@PostMapping("/entPay")
public EntPayResult entPay(@RequestBody EntPayRequest request) throws WxPayException {
return this.wxService.getEntPayService().entPay(request);
}
/**
* <pre>
* 查询企业付款API
* 用于商户的企业付款操作进行结果查询返回付款操作详细结果
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_3
* 接口链接https://api.mch.weixin.qq.com/mmpaymkttransfers/gettransferinfo
* </pre>
*
* @param partnerTradeNo 商户订单号
*/
@ApiOperation(value = "查询企业付款到零钱的结果")
@GetMapping("/queryEntPay/{partnerTradeNo}")
public EntPayQueryResult queryEntPay(@PathVariable String partnerTradeNo) throws WxPayException {
return this.wxService.getEntPayService().queryEntPay(partnerTradeNo);
}
/**
* <pre>
* 获取RSA加密公钥API.
* RSA算法使用说明非对称加密算法算法采用RSA/ECB/OAEPPadding模式
* 1 调用获取RSA公钥API获取RSA公钥落地成本地文件假设为public.pem
* 2 确定public.pem文件的存放路径同时修改代码中文件的输入路径加载RSA公钥
* 3 用标准的RSA加密库对敏感信息进行加密选择RSA_PKCS1_OAEP_PADDING填充模式
* egJava的填充方式要选 " RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING"
* 4 得到进行rsa加密并转base64之后的密文
* 5 将密文传给微信侧相应字段如付款接口enc_bank_no/enc_true_name
*
* 接口默认输出PKCS#1格式的公钥商户需根据自己开发的语言选择公钥格式
* 文档详见:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_7&index=4
* 接口链接https://fraud.mch.weixin.qq.com/risk/getpublickey
* </pre>
*
* @return the public key
* @throws WxPayException the wx pay exception
*/
@ApiOperation(value = "获取RSA加密公钥")
@GetMapping("/getPublicKey")
public String getPublicKey() throws WxPayException {
return this.wxService.getEntPayService().getPublicKey();
}
/**
* 企业付款到银行卡.
* <pre>
* 用于企业向微信用户银行卡付款
* 目前支持接口API的方式向指定微信用户的银行卡付款
* 文档详见https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_2
* 接口链接https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank
* </pre>
*
* @param request 请求对象
* @return the ent pay bank result
* @throws WxPayException the wx pay exception
*/
@ApiOperation(value = "企业付款到银行卡")
@PostMapping("/payBank")
public EntPayBankResult payBank(EntPayBankRequest request) throws WxPayException {
return this.wxService.getEntPayService().payBank(request);
}
/**
* 企业付款到银行卡查询.
* <pre>
* 用于对商户企业付款到银行卡操作进行结果查询返回付款操作详细结果
* 文档详见https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=24_3
* 接口链接https://api.mch.weixin.qq.com/mmpaysptrans/query_bank
* </pre>
*
* @param partnerTradeNo 商户订单号
* @return the ent pay bank query result
* @throws WxPayException the wx pay exception
*/
@ApiOperation(value = "查询企业付款到银行卡的结果")
@GetMapping("/queryPayBank/{partnerTradeNo}")
public EntPayBankQueryResult queryPayBank(@PathVariable String partnerTradeNo) throws WxPayException {
return this.wxService.getEntPayService().queryPayBank(partnerTradeNo);
}
}

View File

@ -0,0 +1,426 @@
package com.ruoyi.wx.pay.controller;
import java.io.File;
import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryRequest;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponInfoQueryResult;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendRequest;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponSendResult;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryRequest;
import com.github.binarywang.wxpay.bean.coupon.WxPayCouponStockQueryResult;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxScanPayNotifyResult;
import com.github.binarywang.wxpay.bean.request.WxPayDownloadBillRequest;
import com.github.binarywang.wxpay.bean.request.WxPayMicropayRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderCloseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayOrderReverseRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundQueryRequest;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayReportRequest;
import com.github.binarywang.wxpay.bean.request.WxPaySendRedpackRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayBillResult;
import com.github.binarywang.wxpay.bean.result.WxPayMicropayResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderCloseResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderReverseResult;
import com.github.binarywang.wxpay.bean.result.WxPayRedpackQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundQueryResult;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.bean.result.WxPaySendRedpackResult;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
/**
* @author Binary Wang
*/
@Api("微信支付")
@RestController
@RequestMapping("/pay")
public class WxPayController {
private WxPayService wxService;
@Autowired
public WxPayController(WxPayService wxService) {
this.wxService = wxService;
}
/**
* <pre>
* 查询订单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_2)
* 该接口提供所有微信支付订单的查询商户可以通过查询订单接口主动查询订单状态完成下一步的业务逻辑
* 需要调用查询接口的情况
* 当商户后台网络服务器等出现异常商户系统最终未接收到支付通知
* 调用支付接口后返回系统错误或未知交易状态情况
* 调用被扫支付API返回USERPAYING的状态
* 调用关单或撤销接口API之前需确认支付状态
* 接口地址https://api.mch.weixin.qq.com/pay/orderquery
* </pre>
*
* @param transactionId 微信订单号
* @param outTradeNo 商户系统内部的订单号当没提供transactionId时需要传这个
*/
@ApiOperation(value = "查询订单")
@GetMapping("/queryOrder")
public WxPayOrderQueryResult queryOrder(@RequestParam(required = false) String transactionId,
@RequestParam(required = false) String outTradeNo)
throws WxPayException {
return this.wxService.queryOrder(transactionId, outTradeNo);
}
@ApiOperation(value = "查询订单")
@PostMapping("/queryOrder")
public WxPayOrderQueryResult queryOrder(WxPayOrderQueryRequest wxPayOrderQueryRequest) throws WxPayException {
return this.wxService.queryOrder(wxPayOrderQueryRequest);
}
/**
* <pre>
* 关闭订单
* 应用场景
* 以下情况需要调用关单接口
* 1. 商户订单支付失败需要生成新单号重新发起支付要对原订单号调用关单避免重复支付
* 2. 系统下单后用户支付超时系统退出不再受理避免用户继续请调用关单接口
* 注意订单生成后不能马上调用关单接口最短调用时间间隔为5分钟
* 接口地址https://api.mch.weixin.qq.com/pay/closeorder
* 是否需要证书 不需要
* </pre>
*
* @param outTradeNo 商户系统内部的订单号
*/
@ApiOperation(value = "关闭订单")
@GetMapping("/closeOrder/{outTradeNo}")
public WxPayOrderCloseResult closeOrder(@PathVariable String outTradeNo) throws WxPayException {
return this.wxService.closeOrder(outTradeNo);
}
@ApiOperation(value = "关闭订单")
@PostMapping("/closeOrder")
public WxPayOrderCloseResult closeOrder(WxPayOrderCloseRequest wxPayOrderCloseRequest) throws WxPayException {
return this.wxService.closeOrder(wxPayOrderCloseRequest);
}
/**
* 调用统一下单接口并组装生成支付所需参数对象.
*
* @param request 统一下单请求参数
* @param <T> 请使用{@link com.github.binarywang.wxpay.bean.order}包下的类
* @return 返回 {@link com.github.binarywang.wxpay.bean.order}包下的类对象
*/
@ApiOperation(value = "统一下单,并组装所需支付参数")
@PostMapping("/createOrder")
public <T> T createOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
return this.wxService.createOrder(request);
}
/**
* 统一下单(详见https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1)
* 在发起微信支付前需要调用统一下单接口获取"预支付交易会话标识"
* 接口地址https://api.mch.weixin.qq.com/pay/unifiedorder
*
* @param request 请求对象注意一些参数如appidmchid等不用设置方法内会自动从配置对象中获取到前提是对应配置中已经设置
*/
@ApiOperation(value = "原生的统一下单接口")
@PostMapping("/unifiedOrder")
public WxPayUnifiedOrderResult unifiedOrder(@RequestBody WxPayUnifiedOrderRequest request) throws WxPayException {
return this.wxService.unifiedOrder(request);
}
/**
* <pre>
* 微信支付-申请退款
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_4
* 接口链接https://api.mch.weixin.qq.com/secapi/pay/refund
* </pre>
*
* @param request 请求对象
* @return 退款操作结果
*/
@ApiOperation(value = "退款")
@PostMapping("/refund")
public WxPayRefundResult refund(@RequestBody WxPayRefundRequest request) throws WxPayException {
return this.wxService.refund(request);
}
/**
* <pre>
* 微信支付-查询退款
* 应用场景
* 提交退款申请后通过调用该接口查询退款状态退款有一定延时用零钱支付的退款20分钟内到账
* 银行卡支付的退款3个工作日后重新查询退款状态
* 详见 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_5
* 接口链接https://api.mch.weixin.qq.com/pay/refundquery
* </pre>
* 以下四个参数四选一
*
* @param transactionId 微信订单号
* @param outTradeNo 商户订单号
* @param outRefundNo 商户退款单号
* @param refundId 微信退款单号
* @return 退款信息
*/
@ApiOperation(value = "退款查询")
@GetMapping("/refundQuery")
public WxPayRefundQueryResult refundQuery(@RequestParam(required = false) String transactionId,
@RequestParam(required = false) String outTradeNo,
@RequestParam(required = false) String outRefundNo,
@RequestParam(required = false) String refundId)
throws WxPayException {
return this.wxService.refundQuery(transactionId, outTradeNo, outRefundNo, refundId);
}
@ApiOperation(value = "退款查询")
@PostMapping("/refundQuery")
public WxPayRefundQueryResult refundQuery(WxPayRefundQueryRequest wxPayRefundQueryRequest) throws WxPayException {
return this.wxService.refundQuery(wxPayRefundQueryRequest);
}
@ApiOperation(value = "支付回调通知处理")
@PostMapping("/notify/order")
public String parseOrderNotifyResult(@RequestBody String xmlData) throws WxPayException {
final WxPayOrderNotifyResult notifyResult = this.wxService.parseOrderNotifyResult(xmlData);
// TODO 根据自己业务场景需要构造返回对象
return WxPayNotifyResponse.success("成功");
}
@ApiOperation(value = "退款回调通知处理")
@PostMapping("/notify/refund")
public String parseRefundNotifyResult(@RequestBody String xmlData) throws WxPayException {
final WxPayRefundNotifyResult result = this.wxService.parseRefundNotifyResult(xmlData);
// TODO 根据自己业务场景需要构造返回对象
return WxPayNotifyResponse.success("成功");
}
@ApiOperation(value = "扫码支付回调通知处理")
@PostMapping("/notify/scanpay")
public String parseScanPayNotifyResult(String xmlData) throws WxPayException {
final WxScanPayNotifyResult result = this.wxService.parseScanPayNotifyResult(xmlData);
// TODO 根据自己业务场景需要构造返回对象
return WxPayNotifyResponse.success("成功");
}
/**
* 发送微信红包给个人用户
* <pre>
* 文档详见:
* 发送普通红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_4&index=3
* 接口地址https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
* 发送裂变红包 https://pay.weixin.qq.com/wiki/doc/api/tools/cash_coupon.php?chapter=13_5&index=4
* 接口地址https://api.mch.weixin.qq.com/mmpaymkttransfers/sendgroupredpack
* </pre>
*
* @param request 请求对象
*/
@ApiOperation(value = "发送红包")
@PostMapping("/sendRedpack")
public WxPaySendRedpackResult sendRedpack(@RequestBody WxPaySendRedpackRequest request) throws WxPayException {
return this.wxService.sendRedpack(request);
}
/**
* <pre>
* 查询红包记录
* 用于商户对已发放的红包进行查询红包的具体信息可支持普通红包和裂变包
* 请求Url https://api.mch.weixin.qq.com/mmpaymkttransfers/gethbinfo
* 是否需要证书 证书及使用说明详见商户证书
* 请求方式 POST
* </pre>
*
* @param mchBillNo 商户发放红包的商户订单号比如10000098201411111234567890
*/
@ApiOperation(value = "查询红包")
@GetMapping("/queryRedpack/{mchBillNo}")
public WxPayRedpackQueryResult queryRedpack(@PathVariable String mchBillNo) throws WxPayException {
return this.wxService.queryRedpack(mchBillNo);
}
/**
* <pre>
* 扫码支付模式一生成二维码的方法
* 二维码中的内容为链接形式为
* weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
* 其中XXXXX为商户需要填写的内容商户将该链接生成二维码如需要打印发布二维码需要采用此格式商户可调用第三方库生成二维码图片
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
* </pre>
*
* @param productId 产品Id
* @param logoFile 商户logo图片的文件对象可以为空
* @param sideLength 要生成的二维码的边长如果为空则取默认值400
* @return 生成的二维码的字节数组
*/
public byte[] createScanPayQrcodeMode1(String productId, File logoFile, Integer sideLength) {
return this.wxService.createScanPayQrcodeMode1(productId, logoFile, sideLength);
}
/**
* <pre>
* 扫码支付模式一生成二维码的方法
* 二维码中的内容为链接形式为
* weixin://wxpay/bizpayurl?sign=XXXXX&appid=XXXXX&mch_id=XXXXX&product_id=XXXXXX&time_stamp=XXXXXX&nonce_str=XXXXX
* 其中XXXXX为商户需要填写的内容商户将该链接生成二维码如需要打印发布二维码需要采用此格式商户可调用第三方库生成二维码图片
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_4
* </pre>
*
* @param productId 产品Id
* @return 生成的二维码URL连接
*/
public String createScanPayQrcodeMode1(String productId) {
return this.wxService.createScanPayQrcodeMode1(productId);
}
/**
* <pre>
* 扫码支付模式二生成二维码的方法
* 对应链接格式weixin//wxpay/bizpayurl?sr=XXXXX请商户调用第三方库将code_url生成二维码图片
* 该模式链接较短生成的二维码打印到结账小票上的识别率较高
* 文档详见: https://pay.weixin.qq.com/wiki/doc/api/native.php?chapter=6_5
* </pre>
*
* @param codeUrl 微信返回的交易会话的二维码链接
* @param logoFile 商户logo图片的文件对象可以为空
* @param sideLength 要生成的二维码的边长如果为空则取默认值400
* @return 生成的二维码的字节数组
*/
public byte[] createScanPayQrcodeMode2(String codeUrl, File logoFile, Integer sideLength) {
return this.wxService.createScanPayQrcodeMode2(codeUrl, logoFile, sideLength);
}
/**
* <pre>
* 交易保障
* 应用场景
* 商户在调用微信支付提供的相关接口时会得到微信支付返回的相关信息以及获得整个接口的响应时间
* 为提高整体的服务水平协助商户一起提高服务质量微信支付提供了相关接口调用耗时和返回信息的主动上报接口
* 微信支付可以根据商户侧上报的数据进一步优化网络部署完善服务监控和商户更好的协作为用户提供更好的业务体验
* 接口地址 https://api.mch.weixin.qq.com/payitil/report
* 是否需要证书不需要
* </pre>
*/
@ApiOperation(value = "提交交易保障数据")
@PostMapping("/report")
public void report(@RequestBody WxPayReportRequest request) throws WxPayException {
this.wxService.report(request);
}
/**
* <pre>
* 下载对账单
* 商户可以通过该接口下载历史交易清单比如掉单系统错误等导致商户侧和微信侧数据不一致通过对账单核对后可校正支付状态
* 注意
* 1微信侧未成功下单的交易不会出现在对账单中支付成功后撤销的交易会出现在对账单中跟原支付单订单号一致bill_type为REVOKED
* 2微信在次日9点启动生成前一天的对账单建议商户10点后再获取
* 3对账单中涉及金额的字段单位为
* 4对账单接口只能下载三个月以内的账单
* 接口链接https://api.mch.weixin.qq.com/pay/downloadbill
* 详情请见: <a href="https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_6">下载对账单</a>
* </pre>
*
* @param billDate 对账单日期 bill_date 下载对账单的日期格式20140603
* @param billType 账单类型 bill_type ALL返回当日所有订单信息默认值SUCCESS返回当日成功支付的订单REFUND返回当日退款订单
* @param tarType 压缩账单 tar_type 非必传参数固定值GZIP返回格式为.gzip的压缩包账单不传则默认为数据流形式
* @param deviceInfo 设备号 device_info 非必传参数终端设备号
* @return 保存到本地的临时文件
*/
@ApiOperation(value = "下载对账单")
@GetMapping("/downloadBill/{billDate}/{billType}/{tarType}/{deviceInfo}")
public WxPayBillResult downloadBill(@PathVariable String billDate,
@PathVariable String billType,
@PathVariable String tarType,
@PathVariable String deviceInfo) throws WxPayException {
return this.wxService.downloadBill(billDate, billType, tarType, deviceInfo);
}
@ApiOperation(value = "下载对账单")
@PostMapping("/downloadBill")
public WxPayBillResult downloadBill(WxPayDownloadBillRequest wxPayDownloadBillRequest) throws WxPayException {
return this.wxService.downloadBill(wxPayDownloadBillRequest);
}
/**
* <pre>
* 提交刷卡支付
* 文档地址https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_10&index=1
* 应用场景
* 收银员使用扫码设备读取微信用户刷卡授权码以后二维码或条码信息传送至商户收银台由商户收银台或者商户后台调用该接口发起支付
* 提醒1提交支付请求后微信会同步返回支付结果当返回结果为系统错误商户系统等待5秒后调用查询订单API查询支付实际交易结果当返回结果为USERPAYING商户系统可设置间隔时间(建议10秒)重新查询支付结果直到支付成功或超时(建议30秒)
* 提醒2在调用查询接口返回后如果交易状况不明晰请调用撤销订单API此时如果交易失败则关闭订单该单不能再支付成功如果交易成功则将扣款退回到用户账户当撤销无返回或错误时请再次调用注意请勿扣款后立即调用撤销订单API,建议至少15秒后再调用撤销订单API需要双向证书
* 接口地址 https://api.mch.weixin.qq.com/pay/micropay
* 是否需要证书不需要
* </pre>
*/
@ApiOperation(value = "提交刷卡支付")
@PostMapping("/micropay")
public WxPayMicropayResult micropay(@RequestBody WxPayMicropayRequest request) throws WxPayException {
return this.wxService.micropay(request);
}
/**
* <pre>
* 撤销订单API
* 文档地址https://pay.weixin.qq.com/wiki/doc/api/micropay.php?chapter=9_11&index=3
* 应用场景
* 支付交易返回失败或支付系统超时调用该接口撤销交易如果此订单用户支付失败微信支付系统会将此订单关闭如果用户支付成功微信支付系统会将此订单资金退还给用户
* 注意7天以内的交易单可调用撤销其他正常支付的单如需实现相同功能请调用申请退款API提交支付交易后调用查询订单API没有明确的支付结果再调用撤销订单API
* 调用支付接口后请勿立即调用撤销订单API建议支付后至少15s后再调用撤销订单接口
* 接口链接 https://api.mch.weixin.qq.com/secapi/pay/reverse
* 是否需要证书请求需要双向证书
* </pre>
*/
@ApiOperation(value = "撤销订单")
@PostMapping("/reverseOrder")
public WxPayOrderReverseResult reverseOrder(@RequestBody WxPayOrderReverseRequest request) throws WxPayException {
return this.wxService.reverseOrder(request);
}
@ApiOperation(value = "获取沙箱环境签名key")
@GetMapping("/getSandboxSignKey")
public String getSandboxSignKey() throws WxPayException {
return this.wxService.getSandboxSignKey();
}
@ApiOperation(value = "发放代金券")
@PostMapping("/sendCoupon")
public WxPayCouponSendResult sendCoupon(@RequestBody WxPayCouponSendRequest request)
throws WxPayException {
return this.wxService.sendCoupon(request);
}
@ApiOperation(value = "查询代金券批次")
@PostMapping("/queryCouponStock")
public WxPayCouponStockQueryResult queryCouponStock(@RequestBody WxPayCouponStockQueryRequest request)
throws WxPayException {
return this.wxService.queryCouponStock(request);
}
@ApiOperation(value = "查询代金券信息")
@PostMapping("/queryCouponInfo")
public WxPayCouponInfoQueryResult queryCouponInfo(@RequestBody WxPayCouponInfoQueryRequest request)
throws WxPayException {
return this.wxService.queryCouponInfo(request);
}
@ApiOperation(value = "拉取订单评价数据")
@PostMapping("/queryComment")
public String queryComment(Date beginDate, Date endDate, Integer offset, Integer limit) throws WxPayException {
return this.wxService.queryComment(beginDate, endDate, offset, limit);
}
}

View File

@ -0,0 +1,29 @@
package com.ruoyi.wx.pay.error;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* <pre>
* 出错页面控制器
* Created by Binary Wang on 2018/8/25.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Controller
@RequestMapping("/error")
public class ErrorController {
@GetMapping(value = "/404")
public String error404() {
return "error";
}
@GetMapping(value = "/500")
public String error500() {
return "error";
}
}

View File

@ -0,0 +1,27 @@
package com.ruoyi.wx.pay.error;
import org.springframework.boot.web.server.ErrorPage;
import org.springframework.boot.web.server.ErrorPageRegistrar;
import org.springframework.boot.web.server.ErrorPageRegistry;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
/**
* <pre>
* 配置错误状态与对应访问路径
* Created by Binary Wang on 2018/8/25.
* </pre>
*
* @author <a href="https://github.com/binarywang">Binary Wang</a>
*/
@Component
public class ErrorPageConfiguration implements ErrorPageRegistrar {
@Override
public void registerErrorPages(ErrorPageRegistry errorPageRegistry) {
errorPageRegistry.addErrorPages(
new ErrorPage(HttpStatus.NOT_FOUND, "/error/404"),
new ErrorPage(HttpStatus.INTERNAL_SERVER_ERROR, "/error/500")
);
}
}

View File

@ -9,4 +9,11 @@ wechat:
- agentId: 1000002
secret: 1111
token: 111
aesKey: 111
aesKey: 111
pay:
appId: #微信公众号或者小程序等的appid
mchId: #微信支付商户号
mchKey: #微信支付商户密钥
subAppId: #服务商模式下的子商户公众账号ID
subMchId: #服务商模式下的子商户号
keyPath: # p12证书的位置可以指定绝对路径也可以指定类路径以classpath:开头)