فهرست منبع

新增微信支付代码

赵冬冬 4 سال پیش
والد
کامیت
90eb5184a5

+ 48 - 0
forest-portal/portal-server/src/main/java/com/hwrj/cloud/portal/config/WxPayConfiguration.java

@@ -0,0 +1,48 @@
+package com.hwrj.cloud.portal.config;
+
+import com.github.binarywang.wxpay.config.WxPayConfig;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
+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;
+
+/**
+ * @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;
+  }
+
+}

+ 97 - 0
forest-portal/portal-server/src/main/java/com/hwrj/cloud/portal/config/WxPayProperties.java

@@ -0,0 +1,97 @@
+package com.hwrj.cloud.portal.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 = "wx.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);
+  }
+}

+ 197 - 0
forest-portal/portal-server/src/main/java/com/hwrj/cloud/portal/controller/AppPayController.java

@@ -0,0 +1,197 @@
+package com.hwrj.cloud.portal.controller;
+
+import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
+import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
+import com.github.binarywang.wxpay.constant.WxPayConstants;
+import com.github.binarywang.wxpay.exception.WxPayException;
+import com.github.binarywang.wxpay.service.WxPayService;
+import com.hwrj.cloud.common.api.CommonResult;
+import com.hwrj.cloud.portal.util.GeneratorIdUtils;
+import com.hwrj.cloud.portal.util.UUIDUtils;
+import com.hwrj.cloud.portal.wxfrom.WxPayFrom;
+import io.swagger.annotations.Api;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.math.BigDecimal;
+
+@Slf4j
+@Controller
+@Api(tags = "AppPayController", description = "支付")
+@RequestMapping("/app")
+public class AppPayController {
+
+    @Value("${wx.pay.wxpayAppcallbackurl}")
+    private String wxpayCallbackUrl;
+
+    @Autowired
+    private WxPayService wxPayService;
+
+    @GetMapping("/pay")
+    @ResponseBody
+    public CommonResult pay(WxPayFrom wxPayFrom, HttpServletRequest request) {
+        String orderId = wxPayFrom.getOrderId();
+        String openid = wxPayFrom.getOpenid();
+        String tradeType = wxPayFrom.getTradeType();
+        //查询订单是否支付
+        int enable = 0;
+        if(1==enable){
+            throw new RuntimeException("订单已支付");
+        }
+        WxPayUnifiedOrderRequest orderRequest = new WxPayUnifiedOrderRequest();
+        //随机字符串
+        String s = UUIDUtils.randomUUID();
+
+        orderRequest.setNonceStr(s);
+        //商品描述
+        orderRequest.setBody("碳汇扶贫!");
+        //商户订单号(支付编号)
+        GeneratorIdUtils generatorIdUtils = new GeneratorIdUtils();
+        String orderNum = generatorIdUtils.nextId();
+        log.info("orderNum:" + orderNum);
+        //设置商户订单号
+        orderRequest.setOutTradeNo(orderNum);
+        //设置支付id
+        //设置金额
+        //data.getTotalPrice();
+        BigDecimal money = new BigDecimal("0.1");
+        //元转成分
+        money = money.multiply(new BigDecimal(100));
+        int i = money.intValue();
+        if ("test".equals(tradeType)) {
+            //测试环境一分钱
+            orderRequest.setTotalFee(1);
+        } else {
+            orderRequest.setTotalFee(i);
+        }
+        //终端ip
+        String ipAddress = getIpAddress(request);
+        orderRequest.setSpbillCreateIp(ipAddress);
+        // 通知地址 支付成功后回调地址
+        log.info("wxpayCallbackUrl=================>{}", wxpayCallbackUrl);
+        orderRequest.setNotifyUrl(wxpayCallbackUrl);
+        //交易类型
+        orderRequest.setTradeType(WxPayConstants.TradeType.APP);
+        //用户标识 获取用户openid
+        orderRequest.setOpenid(openid);
+        // 这个可能是偏向原生一点的统一下单,返回的参数有很多没用的 或者null值 建议使用 createOrder下单
+        Object unOrder = null;
+        try {
+            unOrder = wxPayService.createOrder(orderRequest);
+        } catch (WxPayException e) {
+            //e.printStackTrace();
+            log.error(e.getMessage());
+            //签名完成新增支付订单
+            return CommonResult.failed("微信支付失败");
+        }
+        //更新本地订单支付id
+        //orderClient.update(data);
+        //签名完成新增支付订单
+        return CommonResult.failed("微信支付成功");
+    }
+
+
+    /**
+     * wx支付成功回调接口
+     *
+     * @param request
+     * @param response
+     * @throws IOException
+     */
+    @RequestMapping("payResult")
+    public void payResult(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        log.info("微信支付返回通知函数开始---------------------");
+
+        InputStream inStream = request.getInputStream();
+        ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int len = 0;
+        while ((len = inStream.read(buffer)) != -1) {
+            outSteam.write(buffer, 0, len);
+        }
+        outSteam.close();
+        inStream.close();
+        String result = new String(outSteam.toByteArray(), "utf-8");
+        boolean isPayOk = false;
+        WxPayOrderNotifyResult wxPayOrderNotifyResult = null;
+        // 此处调用订单查询接口验证是否交易成功
+        try {
+            wxPayOrderNotifyResult = wxPayService.parseOrderNotifyResult(result);
+            if ("SUCCESS".equals(wxPayOrderNotifyResult.getResultCode())) {
+                isPayOk = true;
+            }
+            log.info("解析数据:" + wxPayOrderNotifyResult.toString());
+        } catch (WxPayException e) {
+            e.printStackTrace();
+        }
+        String noticeStr = "";
+        // 支付成功,商户处理后同步返回给微信参数
+        PrintWriter writer = response.getWriter();
+        if (isPayOk) {
+            //建议在这里处理付款完成的业务(虽然前端也可以处理后续业务,但是前端处理并不安全,例如:客户突然关闭浏览器了等情况,付款成功后续的业务将中断)
+            //支付订单支付编号
+            System.out.println("===============付款成功,业务开始处理==============");
+            String orderNum = wxPayOrderNotifyResult.getOutTradeNo();
+            log.info("orderNum:" + orderNum);
+
+//            Order order=new Order();
+//            order.setTransId(orderNum);
+//            //将订单更新为支付
+//            orderClient.payment(order);
+            /**
+             * 自己的业务
+             */
+            System.out.println("===============付款成功,业务处理完毕==============");
+            // 通知微信已经收到消息,不要再给我发消息了,否则微信会8连击调用本接口
+            noticeStr = setXML("SUCCESS", "OK");
+            log.info("收到通知返回给微信api信息:-----------" + noticeStr);
+            writer.write(noticeStr);
+            writer.flush();
+        } else {
+            // 支付失败, 记录流水失败
+            noticeStr = setXML("FAIL", "");
+            writer.write(noticeStr);
+            writer.flush();
+            System.out.println("===============支付失败==============");
+        }
+    }
+
+
+
+
+    public static String setXML(String return_code, String return_msg) {
+        return "<xml><return_code><![CDATA[" + return_code + "]]></return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
+    }
+
+    public static String getIpAddress(HttpServletRequest request) {
+        String ip = request.getHeader("x-forwarded-for");
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("WL-Proxy-Client-IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_CLIENT_IP");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getHeader("HTTP_X_FORWARDED_FOR");
+        }
+        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
+            ip = request.getRemoteAddr();
+        }
+        String[] split = ip.split(",");
+        ip = split[0];
+        return ip;
+    }
+
+}

+ 78 - 0
forest-portal/portal-server/src/main/java/com/hwrj/cloud/portal/util/GeneratorIdUtils.java

@@ -0,0 +1,78 @@
+package com.hwrj.cloud.portal.util;
+
+
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.text.SimpleDateFormat;
+
+/**
+ * @zdd
+ */
+public class GeneratorIdUtils {
+    private long workerId;
+    private long datacenterId = 0L;
+    private long sequence = 0L;
+    private long workerIdBits = 8L;
+    private long sequenceBits = 12L;
+    private long workerIdShift;
+    private long datacenterIdShift;
+    private long sequenceMask;
+    private long lastTimestamp;
+
+    public GeneratorIdUtils() {
+        this.workerIdShift = this.sequenceBits;
+        this.datacenterIdShift = this.sequenceBits + this.workerIdBits;
+        this.sequenceMask = ~(-1L << (int)this.sequenceBits);
+        this.lastTimestamp = -1L;
+        this.workerId = (long)(255 & this.getLastIP());
+    }
+
+    public synchronized String nextId() {
+        long timestamp = this.currentTime();
+        if (timestamp < this.lastTimestamp) {
+            throw new RuntimeException(String.format("时钟向后移动。拒绝在%d毫秒内生成id", this.lastTimestamp - timestamp));
+        } else {
+            if (this.lastTimestamp == timestamp) {
+                this.sequence = this.sequence + 1L & this.sequenceMask;
+                if (this.sequence == 0L) {
+                    timestamp = this.nextMillis(this.lastTimestamp);
+                }
+            } else {
+                this.sequence = 0L;
+            }
+
+            this.lastTimestamp = timestamp;
+            long suffix = this.datacenterId << (int)this.datacenterIdShift | this.workerId << (int)this.workerIdShift | this.sequence;
+            SimpleDateFormat timePe = new SimpleDateFormat("yyyyMMddHHMMssSSS");
+            String datePrefix = timePe.format(timestamp);
+            return datePrefix + suffix;
+        }
+    }
+
+    protected long nextMillis(long lastTimestamp) {
+        long timestamp;
+        for(timestamp = this.currentTime(); timestamp <= lastTimestamp; timestamp = this.currentTime()) {
+        }
+
+        return timestamp;
+    }
+
+    protected long currentTime() {
+        return System.currentTimeMillis();
+    }
+
+    private byte getLastIP() {
+        byte lastip = 0;
+
+        try {
+            InetAddress ip = InetAddress.getLocalHost();
+            byte[] ipByte = ip.getAddress();
+            lastip = ipByte[ipByte.length - 1];
+        } catch (UnknownHostException var4) {
+            var4.printStackTrace();
+        }
+
+        return lastip;
+    }
+}

+ 70 - 0
forest-portal/portal-server/src/main/java/com/hwrj/cloud/portal/util/UUIDUtils.java

@@ -0,0 +1,70 @@
+package com.hwrj.cloud.portal.util;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Random;
+import java.util.UUID;
+
+public class UUIDUtils {
+    public UUIDUtils() {
+    }
+
+    public static String randomUUID() {
+        String uuid = UUID.randomUUID().toString();
+        return replace(uuid);
+    }
+
+    public static String replace(String uuid) {
+        return uuid.replaceAll("-", "");
+    }
+
+    public static synchronized String randomOrder() {
+        String code = "";
+        Random rand = new Random();
+
+        for(int a = 0; a < 4; ++a) {
+            code = code + rand.nextInt(10);
+        }
+
+        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
+        String orderNo = sdf.format(new Date()).substring(2) + code;
+        return orderNo;
+    }
+
+    public static String randomOrderLeng(Integer leng) {
+        String code = "";
+        Random rand = new Random();
+
+        for(int a = 0; a < leng; ++a) {
+            code = code + rand.nextInt(10);
+        }
+
+        SimpleDateFormat sdf = new SimpleDateFormat("SSS");
+        String orderNo = "G" + sdf.format(new Date()) + code;
+        return orderNo;
+    }
+
+    public static String randomCertLeng(Integer leng) {
+        String code = "";
+        Random rand = new Random();
+
+        for(int a = 0; a < leng; ++a) {
+            code = code + rand.nextInt(10);
+        }
+
+        return code;
+    }
+
+    public static String setCodeString(Integer lengs, String leng) {
+        String s = "";
+
+        for(int i = 1; i < leng.length(); ++i) {
+            s = s + "0";
+        }
+
+        Integer n = lengs - leng.length();
+        String code = randomCertLeng(n) + s;
+        return code;
+    }
+}
+

+ 14 - 0
forest-portal/portal-server/src/main/java/com/hwrj/cloud/portal/wxfrom/WxPayFrom.java

@@ -0,0 +1,14 @@
+package com.hwrj.cloud.portal.wxfrom;
+
+import lombok.Data;
+
+@Data
+public class WxPayFrom {
+
+    private String orderId;
+
+    private String openid;
+
+    private String tradeType;
+
+}