微信小程序实现统一下单

微信小程序实现统一下单
1.依赖的maven配置

<dependency>
	<groupId>com.github.binarywang</groupId>
	<artifactId>weixin-java-pay</artifactId>
	<version>3.9.0</version>
</dependency>
<dependency>
	<groupId>com.github.binarywang</groupId>
	<artifactId>weixin-java-miniapp</artifactId>
	<version>${weixin4.0.0</version>
</dependency>

2.实体
2.1 微信支付相关参数

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import javax.validation.constraints.Min;
import javax.validation.constraints.NotBlank;

@Data
@ApiModel(value = "auth.WxPayInfoParam", description = "微信支付相关参数")
public class WxPayInfoParam {

	@NotBlank(message = "微信openId不能为空")
    @ApiModelProperty(value = "微信openId", name = "openId", required = true)
    private String openId;

	@Min(value = 0,message = "微信支付金额不能为空")
    @ApiModelProperty(value = "支付金额", name = "fee", required = true)
    private double fee;

    @NotBlank(message = "订单信息")
    @ApiModelProperty(value = "订单信息", name = "orderDesc", required = true)
    private String orderDesc;

    @NotBlank(message = "订单编号不能为空")
    @ApiModelProperty(value = "订单编号", name = "orderId", required = true)
    private String orderId;
}

import cn.gigahome.common.IBaseDto;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

@Data
@ApiModel(value = "auth.WxPayInfoDto", description = "微信支付")
public class WxPayInfoDto implements IBaseDto {

	private static final long serialVersionUID = 1L;

	@ApiModelProperty(value = "appId", name = "appId")
    private String appId;
	
    @ApiModelProperty(value = "nonceStr", name = "nonceStr")
    private String nonceStr;
    
    @ApiModelProperty(value = "paySign", name = "paySign")
    private String paySign;

    @ApiModelProperty(value = "signType", name = "signType")
    private String signType;

    @ApiModelProperty(value = "prepayId", name = "prepayId")
    private String prepayId;

    @ApiModelProperty(value = "timeStamp", name = "timeStamp")
    private String timeStamp;
}

import com.google.common.reflect.TypeToken;
import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

import static io.netty.util.internal.StringUtil.byteToHexString;

public class WxPayUtil {

    /**
     * xml解析
     * @param strxml
     * @return
     * @throws JDOMException
     * @throws IOException
     */
    public static Map doXMLParse(String strxml) throws JDOMException, IOException {
        strxml = strxml.replaceFirst("encoding=\".*\"", "encoding=\"UTF-8\"");

        if(null == strxml || "".equals(strxml)) {
            return null;
        }

        Map m = new HashMap();

        InputStream in = new ByteArrayInputStream(strxml.getBytes("UTF-8"));
        SAXBuilder builder = new SAXBuilder();
        Document doc = builder.build(in);
        Element root = doc.getRootElement();
        List list = root.getChildren();
        Iterator it = list.iterator();
        while(it.hasNext()) {
            Element e = (Element) it.next();
            String k = e.getName();
            String v = "";
            List children = e.getChildren();
            if(children.isEmpty()) {
                v = e.getTextNormalize();
            } else {
                v = getChildrenText(children);
            }

            m.put(k, v);
        }

        //关闭流
        in.close();

        return m;
    }

    public static String getChildrenText(List children) {
        StringBuffer sb = new StringBuffer();
        if(!children.isEmpty()) {
            Iterator it = children.iterator();
            while(it.hasNext()) {
                Element e = (Element) it.next();
                String name = e.getName();
                String value = e.getTextNormalize();
                List list = e.getChildren();
                sb.append("<" + name + ">");
                if(!list.isEmpty()) {
                    sb.append(getChildrenText(list));
                }
                sb.append(value);
                sb.append("</" + name + ">");
            }
        }

        return sb.toString();
    }

    /**
     * 回调签名验证
     * @param map
     * @return
     */
    public static boolean isTenpaySign(Map<String, String> map) {
        String signFromAPIResponse = map.get("sign");
        String key = map.get("key");
        if (signFromAPIResponse == null || signFromAPIResponse.equals("")) {
            System.out.println("API返回的数据签名数据不存在,有可能被第三方篡改!!!");
            return false;
        }
        System.out.println("服务器回包里面的签名是:" + signFromAPIResponse);
        //过滤空 设置 TreeMap
        SortedMap<String,String> packageParams = new TreeMap();

        for (String parameter : map.keySet()) {
            String parameterValue = map.get(parameter);
            String v = "";
            if (null != parameterValue) {
                v = parameterValue.trim();
            }
            packageParams.put(parameter, v);
        }

        StringBuffer sb = new StringBuffer();
        Set es = packageParams.entrySet();
        Iterator it = es.iterator();

        while(it.hasNext()) {
            Map.Entry entry = (Map.Entry)it.next();
            String k = (String)entry.getKey();
            String v = (String)entry.getValue();
            if(!"sign".equals(k) && !"key".equals(k) && null != v && !"".equals(v)) {
                sb.append(k + "=" + v + "&");
            }
        }
        System.out.println(sb);
         sb.append("key=" +key);

        //将API返回的数据根据用签名算法进行计算新的签名,用来跟API返回的签名进行比较
        //算出签名
        String tobesign = sb.toString();
        System.out.println("sb = "+ sb);
        String resultSign=stringToMD5(tobesign);
        String tenpaySign = signFromAPIResponse.toUpperCase();

        return tenpaySign.trim().equals(resultSign.trim().toUpperCase());
    }


    /**
     * md5加密
     * @param plainText
     * @return
     */
    public static String stringToMD5(String plainText) {
        byte[] secretBytes = null;
        try {
            secretBytes = MessageDigest.getInstance("md5").digest(
                    plainText.getBytes());
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("没有这个md5算法!");
        }
        String md5code = new BigInteger(1, secretBytes).toString(16);
        for (int i = 0; i < 32 - md5code.length(); i++) {
            md5code = "0" + md5code;
        }
        return md5code;
    }

    /**
     * 回调通知
     * @param param
     * @return
     */
    public static String GetMapToXML(Map<String,String> param){
        StringBuffer sb = new StringBuffer();
        sb.append("<xml>");
        for (Map.Entry<String,String> entry : param.entrySet()) {
            sb.append("<"+ entry.getKey() +">");
            sb.append(entry.getValue());
            sb.append("</"+ entry.getKey() +">");
        }
        sb.append("</xml>");
        return sb.toString();
    }


    /**
     * 1 块钱转为 100 分
     * 元转分
     *
     * @param bigDecimal 钱数目
     * @return 分
     */
    public static int yuanToFee(BigDecimal bigDecimal) {
        return bigDecimal.multiply(new BigDecimal(100)).intValue();
    }

    public static Integer changeY2F(double amount){
        return (BigDecimal.valueOf(amount).multiply(new BigDecimal(100))).intValue();
    }


    /**
     * 时间
     *
     * @return 时间戳
     */
    public static String createTimestamp() {
        return Long.toString(System.currentTimeMillis() / 1000);
    }


    private static String byteArrayToHexString(byte b[]) {
        StringBuffer resultSb = new StringBuffer();
        for (int i = 0; i < b.length; i++)
            resultSb.append(byteToHexString(b[i]));

        return resultSb.toString();
    }
}

import cn.gigahome.auth.dto.WxPayInfoDto;
import cn.gigahome.auth.param.WxPayInfoParam;
import cn.gigahome.common.ResponseEntity;
import cn.gigahome.common.web.Anonymous;
import cn.gigahome.config.wx.WxPayUtil;
import cn.gigahome.crm.entity.BillUtilityEntity;
import cn.gigahome.crm.entity.ParkingOrderEntity;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.util.SignUtils;
import io.swagger.annotations.ApiOperation;
import org.jdom2.JDOMException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.util.HashMap;
import java.util.Map;

public class TestController {
    @Autowired
    private WxPayService wxPayService;


    //设置微信公众号或者小程序等的appid
    private static final String appId="";
    //微信支付商户号
    private static final String mchId="";
    //微信支付商户密钥
    private static final String mchKey="";

    @GetMapping("/wxGetPay")
    @ApiOperation("微信支付")
    public ResponseEntity<WxPayInfoDto> wxGetPay(WxPayInfoParam param) {
        WxPayUnifiedOrderResult wxPayUnifiedOrderResult =null;

        try {
            final WxPayUnifiedOrderRequest wxPayUnifiedOrderRequest = WxPayUnifiedOrderRequest.newBuilder()
                    //调起支付的人的 openId
                    .openid(param.getOpenId())
                    //订单编号,需要后台生成
                    .outTradeNo(param.getOrderId()).tradeType("JSAPI").productId(param.getOrderId()).detail(param.getOrderDesc())
                    //订单金额
                    .totalFee(WxPayUtil.yuanToFee(new BigDecimal(param.getFee())))
                    //商品描述
                    .body(param.getOrderDesc())
                    //获取本地IP
                    .spbillCreateIp(InetAddress.getLoopbackAddress().getHostAddress())
                    //回调的 URL 地址
                    .notifyUrl("http://bjjg.kaisatech.com/api/crm/wxpay/wxPayNotify")
                    .build();

            wxPayUnifiedOrderResult = wxPayService.unifiedOrder(wxPayUnifiedOrderRequest);
        } catch (WxPayException e) {
            e.printStackTrace();
            System.out.println("微信支付调起失败 == " + e.getMessage());
        }

        //组合参数构建支付
        WxPayInfoDto returnPayInfo = new WxPayInfoDto();
        Map<String, String> paySignInfo = new HashMap<>(5);
        String timeStamp = WxPayUtil.createTimestamp();
        String nonceStr = String.valueOf(System.currentTimeMillis());
        paySignInfo.put("appId", appId);
        paySignInfo.put("nonceStr", nonceStr);
        paySignInfo.put("timeStamp", timeStamp);
        paySignInfo.put("signType", "MD5");
        paySignInfo.put("package", "prepay_id=" + wxPayUnifiedOrderResult.getPrepayId());
        String paySign = SignUtils.createSign(paySignInfo, "MD5", mchKey, null);

        System.out.println("paySign = " + paySign);

        //组合支付参数并返回给前台
        returnPayInfo.setAppId(appId);
        returnPayInfo.setNonceStr(nonceStr);
        returnPayInfo.setPaySign(paySign);
        returnPayInfo.setSignType("MD5");
        returnPayInfo.setPrepayId(wxPayUnifiedOrderResult.getPrepayId());
        returnPayInfo.setTimeStamp(timeStamp);

        return ResponseEntity.success(returnPayInfo);
    }

    @Anonymous
    @ResponseBody
    @ApiOperation("微信支付回调")
    @RequestMapping("/wxPayNotify")
    public String payNotify(HttpServletRequest request, HttpServletResponse response) {
        try {
            System.out.println("微信支付回调");
            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);
            }
            String resultxml = new String(outSteam.toByteArray(), "utf-8");
            Map<String, String> params = WxPayUtil.doXMLParse(resultxml);
            System.out.println(params);
            outSteam.close();
            inStream.close();

            params.put("key",mchKey);

            Map<String,String> return_data = new HashMap<String,String>();
            if(WxPayUtil.isTenpaySign(params)) {
                System.out.println("验证通过");
                // 支付成功
                String out_trade_no = params.get("out_trade_no");
                if (updateCallbackState(return_data, out_trade_no)) {
                    return WxPayUtil.GetMapToXML(return_data);
                }

            } else {
                // 支付失败
                return_data.put("return_code", "FAIL");
                return_data.put("return_msg", "return_code不正确");
                return WxPayUtil.GetMapToXML(return_data);
            }
        } catch (IOException | JDOMException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 修改支付回调状态
     * @param return_data 返回参数
     * @param out_trade_no 订单号
     * @return
     */
    private boolean updateCallbackState(Map<String, String> return_data, String out_trade_no) {
        boolean flag= false;
        if(out_trade_no.startsWith("sd")){
            //通过订单号修改业务逻辑
        }else{
            // 支付失败
            return_data.put("return_code", "FAIL");
            return_data.put("return_msg", "return_code不正确");
            return true;
        }
        if(flag){
            //回调通知微信
            return_data.put("return_code", "SUCCESS");
            return_data.put("return_msg", "OK");
            System.out.println("通知微信成功");
            return true;
        }
        return false;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值