• java版 支付宝和微信 h5支付


    1.支付宝微信支付

    1. <!--引入阿里支付-->
    2. <dependency>
    3. <groupId>com.alipay.sdk</groupId>
    4. <artifactId>alipay-sdk-java</artifactId>
    5. <version>4.38.60.ALL</version>
    6. </dependency>
    AliPayment.java
    1. package com.ruoyi.coupon.payment;
    2. import com.alibaba.fastjson.JSONObject;
    3. import com.alipay.api.AlipayApiException;
    4. import com.alipay.api.CertAlipayRequest;
    5. import com.alipay.api.DefaultAlipayClient;
    6. import com.alipay.api.domain.AlipayTradeAppPayModel;
    7. import com.alipay.api.domain.AlipayTradeRefundModel;
    8. import com.alipay.api.domain.ExtendParams;
    9. import com.alipay.api.internal.util.AlipaySignature;
    10. import com.alipay.api.request.*;
    11. import com.alipay.api.response.*;
    12. import com.ruoyi.common.core.redis.RedisCache;
    13. import com.ruoyi.common.exception.GlobalException;
    14. import com.ruoyi.common.utils.StringUtils;
    15. import com.ruoyi.coupon.payment.dto.PayParam;
    16. import com.ruoyi.coupon.payment.dto.RefundParam;
    17. import com.ruoyi.coupon.service.ICouponConfigService;
    18. import lombok.extern.slf4j.Slf4j;
    19. import org.apache.commons.io.FileUtils;
    20. import org.springframework.beans.factory.annotation.Autowired;
    21. import org.springframework.stereotype.Service;
    22. import javax.servlet.http.HttpServletRequest;
    23. import java.io.File;
    24. import java.io.IOException;
    25. import java.io.InputStream;
    26. import java.io.UnsupportedEncodingException;
    27. import java.util.HashMap;
    28. import java.util.LinkedHashMap;
    29. import java.util.Map;
    30. /**
    31. * 阿里支付类
    32. */
    33. @Service
    34. @Slf4j
    35. public class AliPayment {
    36. private static Map<String,DefaultAlipayClient> aliCertClientMap = new HashMap();
    37. /*public static String appid="";
    38. //应用私钥 参考 https://opendocs.alipay.com/support/01rauw
    39. public static String privateKey="";
    40. //服务商的账户pid 参考 https://opendocs.alipay.com/open/194/105190?pathHash=e479c7e4#%E8%BF%94%E4%BD%A3
    41. public static String sysServiceProviderId="";*/
    42. public static String appid="";
    43. //应用私钥 参考 https://opendocs.alipay.com/support/01rauw
    44. public static String privateKey="";
    45. //服务商的账户pid 参考 https://opendocs.alipay.com/open/194/105190?pathHash=e479c7e4#%E8%BF%94%E4%BD%A3
    46. public static String sysServiceProviderId="";
    47. @Autowired
    48. private RedisCache redisCache;
    49. @Autowired
    50. private ICouponConfigService couponConfigService;
    51. /**
    52. * 获取客户端
    53. * @return
    54. */
    55. public DefaultAlipayClient getAliCertClient() {
    56. DefaultAlipayClient aliCertClient = aliCertClientMap.get("aliCertClient");
    57. if(aliCertClient != null){
    58. return aliCertClient;
    59. }
    60. File appCert = new File("aliPayCert/appCertPublicKey_2021004*******.crt");
    61. File alipayCert = new File("aliPayCert/alipayCertPublicKey_RSA2.crt");
    62. File alipayRootCert = new File("aliPayCert/alipayRootCert.crt");
    63. try {
    64. if (!appCert.exists()) {
    65. InputStream stream = AliPayment.class.getResourceAsStream("/aliPayCert/appCertPublicKey_2021004*******.crt");
    66. FileUtils.copyInputStreamToFile(stream, appCert);
    67. }
    68. if (!alipayCert.exists()) {
    69. InputStream stream = AliPayment.class.getResourceAsStream("/aliPayCert/alipayCertPublicKey_RSA2.crt");
    70. FileUtils.copyInputStreamToFile(stream, alipayCert);
    71. }
    72. if (!alipayRootCert.exists()) {
    73. InputStream stream = AliPayment.class.getResourceAsStream("/aliPayCert/alipayRootCert.crt");
    74. FileUtils.copyInputStreamToFile(stream, alipayRootCert);
    75. }
    76. } catch (IOException e) {
    77. log.error(e.getMessage());
    78. throw new GlobalException(e.getMessage());
    79. }
    80. String appCertPath = appCert.getAbsolutePath();
    81. String alipayCertPath = alipayCert.getAbsolutePath();
    82. String alipayRootCertPath = alipayRootCert.getAbsolutePath();
    83. String privateKey=this.privateKey;
    84. CertAlipayRequest certAlipayRequest = new CertAlipayRequest();
    85. certAlipayRequest.setServerUrl("https://openapi.alipay.com/gateway.do");
    86. certAlipayRequest.setAppId(this.appid);
    87. certAlipayRequest.setPrivateKey(privateKey);
    88. certAlipayRequest.setFormat("JSON");
    89. certAlipayRequest.setCharset("utf-8");
    90. certAlipayRequest.setSignType("RSA2");
    91. certAlipayRequest.setCertPath(appCertPath);
    92. certAlipayRequest.setAlipayPublicCertPath(alipayCertPath);
    93. certAlipayRequest.setRootCertPath(alipayRootCertPath);
    94. DefaultAlipayClient alipayClient = null;
    95. try {
    96. alipayClient = new DefaultAlipayClient(certAlipayRequest);
    97. aliCertClientMap.put("aliCertClient",alipayClient);
    98. } catch (AlipayApiException e) {
    99. e.printStackTrace();
    100. }
    101. return alipayClient;
    102. }
    103. /**
    104. * 下单
    105. * @param payParam
    106. * @return
    107. */
    108. public String pay(PayParam payParam) {
    109. String apiUrl = couponConfigService.getValue("online_domain");
    110. //证书公钥模式
    111. DefaultAlipayClient alipayClient = this.getAliCertClient();
    112. // 创建API对应的request(网页版)
    113. AlipayTradeWapPayRequest request = new AlipayTradeWapPayRequest();
    114. request.setNotifyUrl(apiUrl + "/api/payment/alipay/notify");
    115. //request.setNotifyUrl("http://egevdr.natappfree.cc" + "/payment/alipay/notify");
    116. request.setReturnUrl("");
    117. /******必传参数******/
    118. JSONObject bizContent = new JSONObject();
    119. //商户订单号,商家自定义,保持唯一性
    120. bizContent.put("out_trade_no", payParam.getOutTradeNo());
    121. //支付金额,最小值0.01
    122. bizContent.put("total_amount",payParam.getTotalAmount());
    123. //订单标题,不可使用特殊符号
    124. bizContent.put("subject", payParam.getSubject());
    125. /******可选参数******/
    126. //手机网站支付默认传值FAST_INSTANT_TRADE_PAY
    127. bizContent.put("product_code", "QUICK_WAP_WAY");
    128. //bizContent.put("time_expire", "2022-08-01 22:00:00");
    129. request.setBizContent(bizContent.toString());
    130. try {
    131. AlipayTradeWapPayResponse alipayTradeWapPayResponse = alipayClient.pageExecute(request);
    132. String body = alipayTradeWapPayResponse.getBody();
    133. return body;
    134. } catch (AlipayApiException e) {
    135. e.printStackTrace();
    136. }
    137. return null;
    138. }
    139. /**
    140. * 退款
    141. * @param pefundParam
    142. * @return
    143. */
    144. public Boolean refundOrder(RefundParam pefundParam) {
    145. DefaultAlipayClient alipayClient = this.getAliCertClient();
    146. String apiUrl = couponConfigService.getValue("online_domain");;
    147. AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
    148. JSONObject bizContent = new JSONObject();
    149. bizContent.put("out_trade_no", pefundParam.getOutTradeNo());
    150. bizContent.put("refund_amount", pefundParam.getRefund());
    151. bizContent.put("refund_reason",pefundParam.getBody());
    152. request.setBizContent(bizContent.toString());
    153. //request.setNotifyUrl(apiUrl + "/api/payment/alipay/notify");
    154. try {
    155. AlipayTradeRefundResponse response = alipayClient.certificateExecute(request);
    156. return response.isSuccess();
    157. } catch (AlipayApiException e) {
    158. e.printStackTrace();
    159. }
    160. return null;
    161. }
    162. /**
    163. * 查询订单接口 https://opendocs.alipay.com/open/02ivbt?scene=common&pathHash=8abc6ffe
    164. * @param orderNum
    165. * @return
    166. */
    167. public Map orderQuery(String orderNum) {
    168. DefaultAlipayClient alipayClient = this.getAliCertClient();
    169. AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
    170. JSONObject bizContent = new JSONObject();
    171. bizContent.put("out_trade_no", orderNum);
    172. //bizContent.put("trade_no", "2014112611001004680073956707");
    173. request.setBizContent(bizContent.toString());
    174. try {
    175. AlipayTradeQueryResponse alipayTradeQueryResponse = alipayClient.certificateExecute(request);
    176. Map map=new HashMap();
    177. map.put("tradeState",alipayTradeQueryResponse.getTradeStatus());
    178. /**
    179. * 交易状态:WAIT_BUYER_PAY(交易创建,等待买家付款)、TRADE_CLOSED(未付款交易超时关闭,或支付完成后全额退款)、TRADE_SUCCESS(交易支付成功)、TRADE_FINISHED(交易结束,不可退款)
    180. */
    181. return map;
    182. } catch (AlipayApiException e) {
    183. e.printStackTrace();
    184. }
    185. return null;
    186. }
    187. /**
    188. * 公钥证书模式效验签名
    189. * @param request
    190. * @return
    191. */
    192. public boolean ZSRsaCheck(HttpServletRequest request){
    193. /**
    194. * 支付宝线上的验签需要的支付宝公钥证书
    195. */
    196. File alipayCert = new File("aliPayCert/alipayCertPublicKey_RSA2.crt");
    197. try {
    198. if (!alipayCert.exists()) {
    199. InputStream stream = AliPayment.class.getResourceAsStream("/aliPayCert/alipayCertPublicKey_RSA2.crt");
    200. FileUtils.copyInputStreamToFile(stream, alipayCert);
    201. }
    202. } catch (IOException e) {
    203. log.error("alipayCertPublicKey 证书文件未找到:{}",e.getMessage());
    204. throw new GlobalException(e.getMessage());
    205. }
    206. //支付宝公钥证书
    207. String alipayPublicCertPath=alipayCert.getAbsolutePath();
    208. /**
    209. * 这种方式效率高一点
    210. */
    211. //签名方式
    212. String sign_type="RSA2";
    213. //对待签名字符串数据通过&进行拆分
    214. Map requestParams = request.getParameterMap();
    215. LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
    216. //把拆分数据放在map集合内
    217. for (Object o : requestParams.keySet()) {
    218. String name = (String) o;
    219. String[] values = (String[]) requestParams.get(name);
    220. String valueStr = "";
    221. for (int i = 0; i < values.length; i++) {
    222. valueStr = (i == values.length - 1) ? valueStr + values[i]
    223. : valueStr + values[i] + ",";
    224. }
    225. map.put(name, valueStr);
    226. }
    227. try {
    228. return AlipaySignature.rsaCertCheckV1(map, alipayPublicCertPath, "utf-8",sign_type);
    229. } catch (AlipayApiException e) {
    230. log.error("支付宝异步验签失败:{}",e.getMessage());
    231. return false;
    232. }
    233. }
    234. /**
    235. * 支付宝转账
    236. * @param param
    237. * @return
    238. */
    239. public Map alipayTransfer(Map param){
    240. //获得公钥证书模式支付宝客户端
    241. DefaultAlipayClient aliCertClient = getAliCertClient();
    242. AlipayFundTransUniTransferRequest request = new AlipayFundTransUniTransferRequest();
    243. request.setBizContent("{" +
    244. "\"out_biz_no\":\""+param.get("outBizNo")+"\"," +
    245. "\"trans_amount\":"+param.get("transAmount")+"," +
    246. "\"product_code\":\"TRANS_ACCOUNT_NO_PWD\"," +
    247. "\"biz_scene\":\"DIRECT_TRANSFER\"," +
    248. "\"order_title\":\""+param.get("orderTitle")+"\"," +
    249. "\"payee_info\":{" +
    250. "\"identity_type\":\"ALIPAY_LOGON_ID\"," +
    251. "\"identity\":\""+param.get("identity")+"\"," +
    252. "\"name\":\""+param.get("name")+"\"" +
    253. "}," +
    254. "\"remark\":\""+param.get("remark")+"\"," +
    255. "\"business_params\":{\"payer_show_name_use_alias\":\"true\"}" +
    256. "}");
    257. //返回的map
    258. Map rmap=new HashMap();
    259. try {
    260. AlipayFundTransUniTransferResponse response = aliCertClient.certificateExecute(request);
    261. rmap.put("isSuccess",response.isSuccess());
    262. rmap.put("subMsg",response.getSubMsg());
    263. return rmap;
    264. } catch (AlipayApiException e) {
    265. e.printStackTrace();
    266. return rmap;
    267. }
    268. }
    269. }
    AlipayNotify.java
    1. package com.ruoyi.api.controller.coupon.payment.rest;
    2. import com.ruoyi.common.utils.StringUtils;
    3. import com.ruoyi.coupon.payment.AliPayment;
    4. import com.ruoyi.coupon.payment.enums.AliPayStatusEnum;
    5. import com.ruoyi.coupon.payment.event.PaymentEvent;
    6. import lombok.RequiredArgsConstructor;
    7. import lombok.extern.slf4j.Slf4j;
    8. import org.springframework.beans.factory.annotation.Autowired;
    9. import org.springframework.context.ApplicationEventPublisher;
    10. import org.springframework.http.HttpStatus;
    11. import org.springframework.http.ResponseEntity;
    12. import org.springframework.web.bind.annotation.RequestMapping;
    13. import org.springframework.web.bind.annotation.RequestMethod;
    14. import org.springframework.web.bind.annotation.RestController;
    15. import javax.servlet.http.HttpServletRequest;
    16. import java.io.UnsupportedEncodingException;
    17. import java.nio.charset.StandardCharsets;
    18. import java.util.HashMap;
    19. import java.util.Map;
    20. @Slf4j
    21. @RestController
    22. @RequestMapping("/payment/alipay")
    23. public class AlipayNotify {
    24. @Autowired
    25. private AliPayment aliPayment;
    26. @Autowired
    27. private ApplicationEventPublisher publisher;
    28. @RequestMapping(value = "/notify", method = {RequestMethod.GET, RequestMethod.POST})
    29. @SuppressWarnings("all")
    30. public ResponseEntity<Object> notify(HttpServletRequest request) throws UnsupportedEncodingException {
    31. Map<String, String[]> parameterMap = request.getParameterMap();
    32. //内容验签,防止黑客篡改参数
    33. //if (alipayUtils.rsaCheck(request,alipay)) {
    34. if(aliPayment.ZSRsaCheck(request)){
    35. //交易状态
    36. String tradeStatus = getRequestParameter(request, "trade_status");
    37. // 商户订单号
    38. String outTradeNo = getRequestParameter(request, "out_trade_no");
    39. //支付宝交易号
    40. String tradeNo = getRequestParameter(request, "trade_no");
    41. //付款金额
    42. String totalAmount = getRequestParameter(request, "total_amount");
    43. //退款金额
    44. String refundFee = getRequestParameter(request, "refund_fee");
    45. //获取回传参数paymentType
    46. String passbackParams = getRequestParameter(request, "passback_params");
    47. Map<String,String> map=new HashMap<>();
    48. if(StringUtils.isNotBlank(passbackParams)){
    49. passbackParams= java.net.URLDecoder.decode(passbackParams,"UTF-8");
    50. String[] split = StringUtils.split(passbackParams, ";");
    51. for (int i=0;i<split.length;i++){
    52. String[] split1 = StringUtils.split(split[i], "=");
    53. map.put(split1[0],split1[1]);
    54. }
    55. }
    56. //记录日志
    57. if (StringUtils.isNotEmpty(refundFee)) {
    58. log.info(">>>>> 交易状态: {}, 商户订单号: {}, 支付宝交易号: {}, 退款金额: {}", tradeStatus, outTradeNo, tradeNo, refundFee);
    59. //验证
    60. if (AliPayStatusEnum.CLOSED.getValue().equals(tradeStatus)) {
    61. // outTradeNo 退款成功
    62. publisher.publishEvent(new PaymentEvent(this, outTradeNo,1,map,refundFee));
    63. }
    64. } else if (StringUtils.isNotEmpty(totalAmount)) {
    65. log.info(">>>>> 交易状态: {}, 商户订单号: {}, 支付宝交易号: {}, 付款金额: {}", tradeStatus, outTradeNo, tradeNo, totalAmount);
    66. //验证
    67. if (AliPayStatusEnum.SUCCESS.getValue().equals(tradeStatus) || AliPayStatusEnum.FINISHED.getValue().equals(tradeStatus)) {
    68. // outTradeNo 支付成功
    69. publisher.publishEvent(new PaymentEvent(this, outTradeNo,0,map,totalAmount));
    70. }
    71. } else {
    72. log.info(">>>>> 交易状态: {}, 商户订单号: {}, 支付宝交易号: {}", tradeStatus, outTradeNo, tradeNo);
    73. }
    74. return new ResponseEntity<>("success",HttpStatus.OK);//返回success ,让支付宝不在重复调起回调
    75. }
    76. return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
    77. }
    78. private String getRequestParameter(HttpServletRequest request, String valname) {
    79. String value = request.getParameter(valname);
    80. if (value != null) {
    81. return new String(value.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
    82. }
    83. return value;
    84. }
    85. }

    2.微信支付

    1. <dependency>
    2. <groupId>com.github.wechatpay-apiv3</groupId>
    3. <artifactId>wechatpay-java</artifactId>
    4. <version>0.2.11</version>
    5. </dependency>
    WeChatPayment.java
    1. package com.ruoyi.coupon.payment;
    2. import com.fasterxml.jackson.databind.ObjectMapper;
    3. import com.fasterxml.jackson.databind.node.ObjectNode;
    4. import com.google.gson.Gson;
    5. import com.google.gson.GsonBuilder;
    6. import com.ruoyi.common.exception.GlobalException;
    7. import com.ruoyi.coupon.payment.dto.PayParam;
    8. import com.ruoyi.coupon.payment.dto.RefundParam;
    9. import com.ruoyi.coupon.payment.utils.IpUtil;
    10. import com.ruoyi.coupon.service.ICouponConfigService;
    11. import com.wechat.pay.java.core.Config;
    12. import com.wechat.pay.java.core.RSAAutoCertificateConfig;
    13. import com.wechat.pay.java.core.notification.NotificationConfig;
    14. import com.wechat.pay.java.core.notification.NotificationParser;
    15. import com.wechat.pay.java.core.notification.RequestParam;
    16. import com.wechat.pay.java.service.payments.h5.H5Service;
    17. import com.wechat.pay.java.service.payments.h5.model.*;
    18. import com.wechat.pay.java.service.payments.model.Transaction;
    19. import com.wechat.pay.java.service.payments.model.TransactionAmount;
    20. import com.wechat.pay.java.service.refund.RefundService;
    21. import com.wechat.pay.java.service.refund.model.AmountReq;
    22. import com.wechat.pay.java.service.refund.model.CreateRequest;
    23. import com.wechat.pay.java.service.refund.model.Refund;
    24. import com.wechat.pay.java.service.refund.model.RefundNotification;
    25. import lombok.extern.slf4j.Slf4j;
    26. import org.springframework.beans.factory.annotation.Autowired;
    27. import org.springframework.stereotype.Service;
    28. import javax.servlet.ServletInputStream;
    29. import javax.servlet.http.HttpServletRequest;
    30. import java.io.*;
    31. import java.math.BigDecimal;
    32. import java.nio.charset.StandardCharsets;
    33. import java.security.PrivateKey;
    34. import java.security.cert.X509Certificate;
    35. import java.util.ArrayList;
    36. import java.util.HashMap;
    37. import java.util.Map;
    38. import java.util.UUID;
    39. /**
    40. * 微信支付服务类
    41. */
    42. @Service
    43. @Slf4j
    44. public class WeChatPayment {
    45. private static final String mchId = ""; // 商户号
    46. private static final String mchSerialNo = ""; // 商户证书序列号
    47. //商户私钥 //https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay3_1.shtml
    48. private static final String privateKey = "";
    49. // 你的微信支付平台证书
    50. private static final String apiV3Key = "";
    51. private static final String appid="";
    52. /** 商户API私钥路径 */
    53. public static String privateKeyPath = "C:\\Users\\Administrator\\Desktop\\coupon\\wxpay\\apiclient_key.pem";
    54. @Autowired
    55. private ICouponConfigService couponConfigService;
    56. /**
    57. * 获得H5客户端
    58. * @return
    59. */
    60. public H5Service getH5Service () {
    61. Config config =
    62. new RSAAutoCertificateConfig.Builder()
    63. .merchantId(mchId)
    64. .privateKey(privateKey)
    65. //.privateKeyFromPath(privateKeyPath)
    66. .merchantSerialNumber(mchSerialNo)
    67. .apiV3Key(apiV3Key)
    68. .build();
    69. H5Service build = new H5Service.Builder().config(config).build();
    70. return build;
    71. }
    72. public String pay(PayParam payParam) {
    73. String apiUrl = couponConfigService.getValue("online_domain");
    74. BigDecimal bigDecimal = new BigDecimal(100);
    75. int payPrice = bigDecimal.multiply(new BigDecimal(payParam.getTotalAmount())).intValue();
    76. H5Service h5Service = getH5Service();
    77. //获取客户端
    78. PrepayRequest request = new PrepayRequest();
    79. Amount amount = new Amount();
    80. amount.setTotal(payPrice);
    81. H5Info h5Info = new H5Info();
    82. h5Info.setType("Wap");
    83. //场景信息
    84. SceneInfo sceneInfo = new SceneInfo();
    85. sceneInfo.setPayerClientIp("qy.gsjf.cc");
    86. sceneInfo.setH5Info(h5Info);
    87. request.setAmount(amount);
    88. request.setAppid(appid);
    89. request.setMchid(mchId);
    90. request.setDescription(payParam.getSubject());
    91. //request.setNotifyUrl("http://egevdr.natappfree.cc" + "/payment/weChatPay/payment/notify");
    92. request.setNotifyUrl(apiUrl +"api" + "/payment/weChatPay/payment/notify");
    93. request.setOutTradeNo(payParam.getOutTradeNo());
    94. request.setAttach(payParam.getPassbackParams());//携带其他参数
    95. request.setSceneInfo(sceneInfo);
    96. // 调用下单方法,得到应答
    97. PrepayResponse prepay = h5Service.prepay(request);
    98. return prepay.getH5Url();
    99. }
    100. /**
    101. * 申请退款
    102. * @param refundParam
    103. */
    104. public void refundOrder(RefundParam refundParam) {
    105. String apiUrl = couponConfigService.getValue("online_domain");
    106. BigDecimal bigDecimal = new BigDecimal(100);
    107. int total = bigDecimal.multiply(new BigDecimal(refundParam.getTotal())).intValue();
    108. int refund = bigDecimal.multiply(new BigDecimal(refundParam.getRefund())).intValue();
    109. Config config =
    110. new RSAAutoCertificateConfig.Builder()
    111. .merchantId(mchId)
    112. .privateKey(privateKey)
    113. .merchantSerialNumber(mchSerialNo)
    114. .apiV3Key(apiV3Key)
    115. .build();
    116. RefundService service = new RefundService.Builder().config(config).build();
    117. //生成随机退款订单号
    118. String s = UUID.randomUUID().toString().replace("-","");
    119. CreateRequest request = new CreateRequest();
    120. //金额信息
    121. AmountReq amount = new AmountReq();
    122. amount.setCurrency("CNY");
    123. amount.setTotal(Long.valueOf(total));
    124. amount.setRefund(Long.valueOf(refund));
    125. request.setAmount(amount);
    126. request.setOutTradeNo(refundParam.getOutTradeNo());
    127. request.setOutRefundNo(s);
    128. //request.setNotifyUrl("http://egevdr.natappfree.cc" + "/payment/weChatPay/refund/notify");
    129. request.setNotifyUrl(apiUrl +"api" + "/payment/weChatPay/refund/notify");
    130. //发送请求
    131. Refund refund1 = service.create(request);
    132. }
    133. /**
    134. * 根据订单号查询订单信息,目前只返回了订单状态 https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_3_2.shtml
    135. * @param orderNum
    136. * @return
    137. */
    138. public Map queryOrderByOutTradeNo(String orderNum) {
    139. H5Service h5Service = getH5Service();
    140. QueryOrderByOutTradeNoRequest request = new QueryOrderByOutTradeNoRequest();
    141. request.setMchid(mchId);
    142. request.setOutTradeNo(orderNum);
    143. Transaction transaction = h5Service.queryOrderByOutTradeNo(request);
    144. Map map=new HashMap();
    145. map.put("tradeState",transaction.getTradeState());
    146. /**
    147. * 交易状态,枚举值:
    148. * SUCCESS:支付成功
    149. * REFUND:转入退款
    150. * NOTPAY:未支付
    151. * CLOSED:已关闭
    152. * REVOKED:已撤销(仅付款码支付会返回)
    153. * USERPAYING:用户支付中(仅付款码支付会返回)
    154. * PAYERROR:支付失败(仅付款码支付会返回)
    155. */
    156. return map;
    157. }
    158. /**
    159. * 支付成功验签
    160. * @param request
    161. * @return
    162. */
    163. public Map paySuccessCheck(HttpServletRequest request) {
    164. Config config =
    165. new RSAAutoCertificateConfig.Builder()
    166. .merchantId(mchId)
    167. .privateKey(privateKey)
    168. .merchantSerialNumber(mchSerialNo)
    169. .apiV3Key(apiV3Key)
    170. .build();
    171. // 从请求头中获取信息
    172. String timestamp = request.getHeader("Wechatpay-Timestamp");
    173. String nonce = request.getHeader("Wechatpay-Nonce");
    174. String signature = request.getHeader("Wechatpay-Signature");
    175. String singType = request.getHeader("Wechatpay-Signature-Type");
    176. String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");
    177. String requestBody = getRequestBody(request);
    178. // 构造 RequestParam
    179. RequestParam requestParam = new RequestParam.Builder()
    180. .serialNumber(wechatPayCertificateSerialNumber)
    181. .nonce(nonce)
    182. .signature(signature)
    183. .signType(singType)
    184. .timestamp(timestamp)
    185. .body(requestBody)
    186. .build();
    187. // 初始化解析器 NotificationParser
    188. NotificationParser parser = new NotificationParser((NotificationConfig) config);
    189. // 这个Transaction是微信包里面的
    190. Transaction decryptObject = parser.parse(requestParam, Transaction.class);
    191. TransactionAmount amount = decryptObject.getAmount();
    192. String outTradeNo = decryptObject.getOutTradeNo();
    193. String attach = decryptObject.getAttach();
    194. Map map=new HashMap();
    195. map.put("amount",amount.getTotal());
    196. map.put("outTradeNo",outTradeNo);
    197. map.put("attach",attach);
    198. return map;
    199. }
    200. public Map refundSuccessCheck(HttpServletRequest request) {
    201. Config config =
    202. new RSAAutoCertificateConfig.Builder()
    203. .merchantId(mchId)
    204. .privateKey(privateKey)
    205. .merchantSerialNumber(mchSerialNo)
    206. .apiV3Key(apiV3Key)
    207. .build();
    208. // 从请求头中获取信息
    209. String timestamp = request.getHeader("Wechatpay-Timestamp");
    210. String nonce = request.getHeader("Wechatpay-Nonce");
    211. String signature = request.getHeader("Wechatpay-Signature");
    212. String singType = request.getHeader("Wechatpay-Signature-Type");
    213. String wechatPayCertificateSerialNumber = request.getHeader("Wechatpay-Serial");
    214. String requestBody = getRequestBody(request);
    215. // 构造 RequestParam
    216. RequestParam requestParam = new RequestParam.Builder()
    217. .serialNumber(wechatPayCertificateSerialNumber)
    218. .nonce(nonce)
    219. .signature(signature)
    220. .signType(singType)
    221. .timestamp(timestamp)
    222. .body(requestBody)
    223. .build();
    224. // 初始化解析器 NotificationParser
    225. NotificationParser parser = new NotificationParser((NotificationConfig) config);
    226. // 这个Transaction是微信包里面的
    227. RefundNotification decryptObject = parser.parse(requestParam, RefundNotification.class);
    228. com.wechat.pay.java.service.refund.model.Amount amount = decryptObject.getAmount();
    229. String outTradeNo = decryptObject.getOutTradeNo();
    230. Map map=new HashMap();
    231. map.put("amount",amount.getTotal());
    232. map.put("outTradeNo",outTradeNo);
    233. return map;
    234. }
    235. // 获取请求头里的数据
    236. private String getRequestBody(HttpServletRequest request) {
    237. StringBuffer sb = new StringBuffer();
    238. try (
    239. ServletInputStream inputStream = request.getInputStream();
    240. BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
    241. ) {
    242. String line;
    243. while ((line = reader.readLine()) != null) {
    244. sb.append(line);
    245. }
    246. } catch (IOException e) {
    247. System.out.println("读取数据流异常:"+e);
    248. }
    249. return sb.toString();
    250. }
    251. }
    WeChatPayNotify.java
    1. package com.ruoyi.api.controller.coupon.payment.rest;
    2. import com.ruoyi.common.utils.StringUtils;
    3. import com.ruoyi.coupon.payment.WeChatPayment;
    4. import com.ruoyi.coupon.payment.event.PaymentEvent;
    5. import lombok.extern.slf4j.Slf4j;
    6. import org.springframework.beans.factory.annotation.Autowired;
    7. import org.springframework.context.ApplicationEventPublisher;
    8. import org.springframework.http.HttpStatus;
    9. import org.springframework.http.ResponseEntity;
    10. import org.springframework.transaction.annotation.Transactional;
    11. import org.springframework.web.bind.annotation.PostMapping;
    12. import org.springframework.web.bind.annotation.RequestBody;
    13. import org.springframework.web.bind.annotation.RequestMapping;
    14. import org.springframework.web.bind.annotation.RestController;
    15. import javax.servlet.http.HttpServletRequest;
    16. import javax.servlet.http.HttpServletResponse;
    17. import java.math.BigDecimal;
    18. import java.util.HashMap;
    19. import java.util.Map;
    20. /**
    21. * 商城支付项微信支付的回调接口
    22. */
    23. @Slf4j
    24. @RestController
    25. @RequestMapping("/payment/weChatPay")
    26. public class WeChatPayNotify {
    27. @Autowired
    28. private ApplicationEventPublisher publisher;
    29. @Autowired
    30. private WeChatPayment weChatPayment;
    31. /**
    32. * 微信支付/充值回调
    33. */
    34. @PostMapping("/payment/notify")
    35. public ResponseEntity.BodyBuilder renotify(HttpServletRequest request) {
    36. Map map = weChatPayment.paySuccessCheck(request);
    37. Integer amount = (Integer)map.get("amount");
    38. String outTradeNo = (String)map.get("outTradeNo");
    39. String attach = (String)map.get("attach");
    40. Map<String, Object> map1 = new HashMap<>();
    41. //将附加信息 attach 解析到 map1 中,因为现在没有传递任何参数,所以没有解析
    42. BigDecimal divide = new BigDecimal(amount).divide(new BigDecimal("100"));
    43. publisher.publishEvent(new PaymentEvent(this, outTradeNo,0,map1,divide.toString()));
    44. return ResponseEntity.status(HttpStatus.OK);
    45. }
    46. /**
    47. * 微信退款回调
    48. */
    49. @PostMapping("/refund/notify")
    50. public ResponseEntity.BodyBuilder parseRefundNotifyResult(HttpServletRequest request) {
    51. Map map = weChatPayment.refundSuccessCheck(request);
    52. Long amount = (Long)map.get("amount");
    53. String outTradeNo = (String)map.get("outTradeNo");
    54. BigDecimal divide = new BigDecimal(amount).divide(new BigDecimal("100"));
    55. publisher.publishEvent(new PaymentEvent(this, outTradeNo,1,null,divide.toString()));
    56. return ResponseEntity.status(HttpStatus.OK);
    57. }
    58. }

     前端 uniapp 的调起方式

    1. <view class="alipaysubmit" v-html="formContent"></view>
    2. createOrder(data).then(res=>{
    3. uni.hideLoading()
    4. this.payType=''
    5. if(res.data.payType=="aliPayH5"){
    6. this.formContent=res.data.payStrand
    7. this.$nextTick(() => {
    8. document.forms['punchout_form'].submit();
    9. })
    10. }else if(res.data.payType=="weChatH5"){
    11. const platform = uni.getSystemInfoSync().platform
    12. let mweb_url = res.data.payStrand
    13. var a=document.createElement('a');
    14. switch (platform) {
    15. case 'android':
    16. a.href=mweb_url
    17. a.click()
    18. break;
    19. case 'ios':
    20. a.href=mweb_url
    21. a.click()
    22. break;
    23. default:
    24. break;
    25. }
    26. }else if(res.data.payType=="balance"){
    27. uni.showToast({
    28. title:res.data.payStrand
    29. })
    30. }
    31. uni.navigateTo({
    32. url:"/pages/mine/order/order"
    33. })
    34. })

  • 相关阅读:
    常见机器学习算法的优缺点及如何选择1
    承上启下:基于全域漏斗分析的主搜深度统一粗排
    Springboot毕设项目老来福平台682f5(java+VUE+Mybatis+Maven+Mysql)
    String(三)———接口大全
    [H5动画制作系列] Sprite及Text Demo
    Topic太多,RocketMQ炸了!
    金仓数据库KingbaseES客户端编程接口指南-DCI(5. 程序示例)
    DJ 12-3 程序控制指令
    ubuntu挂载共享目录的方法
    20和遍历以及迭代器有关的一些东西
  • 原文地址:https://blog.csdn.net/qq_31683775/article/details/134081306