APP 对接 java 微信支付统一下单接口

首先插入微信支付的时序图
在这里插入图片描述
统一下单时候的请求对象,需要把这个转为xml 文件格式所以需要在pom.xml 文件中导入 、和微信支付的sdk

<dependency>     
	<groupId>com.github.wxpay</groupId>     
	<artifactId>wxpay-sdk</artifactId>     
	<version>0.0.3</version> 
</dependency>

<deendency>
    <groupId>com.thoughtworks.xstream</groupId>
    <artifactId>xstream</artifactId>
    <version>1.4.10</version>
</dependency>

微信统一下单接口需要的所有参数可以微信官方查看 微信官方统一下单接口

@XmlRootElement(name = "xml")
public class UnifiedOrderRequest {
    private java.lang.String appid;//微信分配的小程序IDwxd678efh567hg6787,NotNull
    private java.lang.String mch_id;//微信支付分配的商户号1230000109,NotNull
    private java.lang.String device_info;//自定义参数,可以为终端设备号(门店号或收银设备ID),PC网页或公众号内支付可以传"WEB"
    private java.lang.String nonce_str;//随机字符串,必须,NotNull
    private java.lang.String sign;//签名,必须,,
    private java.lang.String sign_type;//"HMAC-SHA256"或者"MD5",非必须,默认MD5
    private java.lang.String body;//商品简单描述,必须
    private java.lang.String detail;//商品详细列表,使用json格式
    private java.lang.String attach;//附加数据,如"贵阳分店",非必须(1,代表采购订单  2,代表租凭酒机订单)
    private java.lang.String out_trade_no;//商户系统内部订单号,要求32个字符内,只能是数字、大小写字母_-|*且在同一个商户号下唯一
    private java.lang.String fee_type;//默认人民币:CNY,非必须
    private Integer total_fee;//订单金额,单位分,必须
    private java.lang.String spbill_create_ip;//支付提交客户端IP,如“123.123.123.123”,必须
    private java.lang.String time_start;//订单生成时间,格式为yyyyMMddHHmmss,如20170324094700,非必须
    private java.lang.String time_expire;//订单结束时间,格式同上,非必须
    private java.lang.String goods_tag;//订单优惠标记,代金券或立减优惠功能的参数,非必须
    private java.lang.String notify_url;//接收微信支付异步通知回调地址,不能携带参数,必须
    private java.lang.String trade_type;//交易类型,小程序写"JSAPI",必须
    private java.lang.String product_id;//商品ID trade_type=NATIVE时(即扫码支付),此参数必传。此参数为二维码中包含的商品ID,商户自行定义。
    private java.lang.String limit_pay;//限制某种支付方式,非必须
    private java.lang.String openid;//微信用户唯一标识,必须
    private String scene_info;//h5支付必须  (场景信息)

    public UnifiedOrderRequest(java.lang.String openid, java.lang.String appid, java.lang.String mchId, java.lang.String deviceId,
                               java.lang.String nonceStr, java.lang.String body, java.lang.String outTradeNo, Integer totalFee,
                               java.lang.String spbillCreateIp, java.lang.String notifyUrl, java.lang.String tradeType, java.lang.String productId) {
        this.openid = openid;
        this.appid = appid;
        this.mch_id = mchId;
        this.device_info = deviceId;
        this.nonce_str = nonceStr;
        this.body = body;
        this.out_trade_no = outTradeNo;
        this.total_fee = totalFee;
        this.spbill_create_ip = spbillCreateIp;
        this.notify_url = notifyUrl;
        this.trade_type = tradeType;
        this.product_id = productId;
    }

    public UnifiedOrderRequest(java.lang.String appid, java.lang.String machid, java.lang.String nonceStr, java.lang.String body, java.lang.String outTradeNo, Integer totalFee, java.lang.String spbillCreateIp, java.lang.String notifyUrl, java.lang.String trade_type, String string) {
        this.appid = appid;
        this.mch_id = machid;
        this.nonce_str = nonceStr;
        this.body = body;
        this.out_trade_no = outTradeNo;
        this.total_fee = totalFee;
        this.spbill_create_ip = spbillCreateIp;
        this.notify_url = notifyUrl;
        this.trade_type = trade_type;
        this.scene_info = string;
    }


    public String getScene_info() {
        return scene_info;
    }

    public void setScene_info(String scene_info) {
        this.scene_info = scene_info;
    }

    public java.lang.String getAppid() {
        return appid;
    }

    public void setAppid(java.lang.String appid) {
        this.appid = appid;
    }

    public java.lang.String getMch_id() {
        return mch_id;
    }

    public void setMch_id(java.lang.String mch_id) {
        this.mch_id = mch_id;
    }

    public java.lang.String getDevice_info() {
        return device_info;
    }

    public void setDevice_info(java.lang.String device_info) {
        this.device_info = device_info;
    }

    public java.lang.String getNonce_str() {
        return nonce_str;
    }

    public void setNonce_str(java.lang.String nonce_str) {
        this.nonce_str = nonce_str;
    }

    public java.lang.String getSign() {
        return sign;
    }

    public void setSign(java.lang.String sign) {
        this.sign = sign;
    }

    public java.lang.String getSign_type() {
        return sign_type;
    }

    public void setSign_type(java.lang.String sign_type) {
        this.sign_type = sign_type;
    }

    public java.lang.String getBody() {
        return body;
    }

    public void setBody(java.lang.String body) {
        this.body = body;
    }

    public java.lang.String getDetail() {
        return detail;
    }

    public void setDetail(java.lang.String detail) {
        this.detail = detail;
    }

    public java.lang.String getAttach() {
        return attach;
    }

    public void setAttach(java.lang.String attach) {
        this.attach = attach;
    }

    public java.lang.String getOut_trade_no() {
        return out_trade_no;
    }

    public void setOut_trade_no(java.lang.String out_trade_no) {
        this.out_trade_no = out_trade_no;
    }

    public java.lang.String getFee_type() {
        return fee_type;
    }

    public void setFee_type(java.lang.String fee_type) {
        this.fee_type = fee_type;
    }

    public Integer getTotal_fee() {
        return total_fee;
    }

    public void setTotal_fee(Integer total_fee) {
        this.total_fee = total_fee;
    }

    public java.lang.String getSpbill_create_ip() {
        return spbill_create_ip;
    }

    public void setSpbill_create_ip(java.lang.String spbill_create_ip) {
        this.spbill_create_ip = spbill_create_ip;
    }

    public java.lang.String getTime_start() {
        return time_start;
    }

    public void setTime_start(java.lang.String time_start) {
        this.time_start = time_start;
    }

    public java.lang.String getTime_expire() {
        return time_expire;
    }

    public void setTime_expire(java.lang.String time_expire) {
        this.time_expire = time_expire;
    }

    public java.lang.String getGoods_tag() {
        return goods_tag;
    }

    public void setGoods_tag(java.lang.String goods_tag) {
        this.goods_tag = goods_tag;
    }

    public java.lang.String getNotify_url() {
        return notify_url;
    }

    public void setNotify_url(java.lang.String notify_url) {
        this.notify_url = notify_url;
    }

    public java.lang.String getTrade_type() {
        return trade_type;
    }

    public void setTrade_type(java.lang.String trade_type) {
        this.trade_type = trade_type;
    }

    public java.lang.String getProduct_id() {
        return product_id;
    }

    public void setProduct_id(java.lang.String product_id) {
        this.product_id = product_id;
    }

    public java.lang.String getLimit_pay() {
        return limit_pay;
    }

    public void setLimit_pay(java.lang.String limit_pay) {
        this.limit_pay = limit_pay;
    }

    public java.lang.String getOpenid() {
        return openid;
    }

    public void setOpenid(java.lang.String openid) {
        this.openid = openid;
    }

    public UnifiedOrderRequest() {
    }

    public UnifiedOrderRequest(java.lang.String appid, java.lang.String mch_id, java.lang.String device_info, java.lang.String nonce_str, java.lang.String sign, java.lang.String sign_type, java.lang.String body, java.lang.String detail, java.lang.String attach, java.lang.String out_trade_no, java.lang.String fee_type, Integer total_fee, java.lang.String spbill_create_ip, java.lang.String time_start, java.lang.String time_expire, java.lang.String goods_tag, java.lang.String notify_url, java.lang.String trade_type, java.lang.String product_id, java.lang.String limit_pay, java.lang.String openid) {
        this.appid = appid;
        this.mch_id = mch_id;
        this.device_info = device_info;
        this.nonce_str = nonce_str;
        this.sign = sign;
        this.sign_type = sign_type;
        this.body = body;
        this.detail = detail;
        this.attach = attach;
        this.out_trade_no = out_trade_no;
        this.fee_type = fee_type;
        this.total_fee = total_fee;
        this.spbill_create_ip = spbill_create_ip;
        this.time_start = time_start;
        this.time_expire = time_expire;
        this.goods_tag = goods_tag;
        this.notify_url = notify_url;
        this.trade_type = trade_type;
        this.product_id = product_id;
        this.limit_pay = limit_pay;
        this.openid = openid;
    }

    @Override
    public java.lang.String toString() {
        return "UnifiedOrderRequest{" +
                "appid='" + appid + '\'' +
                ", mch_id='" + mch_id + '\'' +
                ", device_info='" + device_info + '\'' +
                ", nonce_str='" + nonce_str + '\'' +
                ", sign='" + sign + '\'' +
                ", sign_type='" + sign_type + '\'' +
                ", body='" + body + '\'' +
                ", detail='" + detail + '\'' +
                ", attach='" + attach + '\'' +
                ", out_trade_no='" + out_trade_no + '\'' +
                ", fee_type='" + fee_type + '\'' +
                ", total_fee=" + total_fee +
                ", spbill_create_ip='" + spbill_create_ip + '\'' +
                ", time_start='" + time_start + '\'' +
                ", time_expire='" + time_expire + '\'' +
                ", goods_tag='" + goods_tag + '\'' +
                ", notify_url='" + notify_url + '\'' +
                ", trade_type='" + trade_type + '\'' +
                ", product_id='" + product_id + '\'' +
                ", limit_pay='" + limit_pay + '\'' +
                ", openid='" + openid + '\'' +
                '}';
    }
}

微信支付统一下单的响应字段 可以通过 微信官方统一下单接口

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name = "xml")
public class UnifiedOrderResponse {
    private String return_code;//返回状态码
    private String return_msg;//返回信息
    private String appid;//小程序ID
    private String mch_id;//商户号
    private String device_info;//设备号
    private String nonce_str;//随机字符串
    private String sign;//签名
    private String result_code;//业务结果
    private String err_code;//错误代码
    private String err_code_des;//错错误代码描述
    private String trade_type;//交易类型
    private String prepay_id;//预支付交易会话标识
    private String code_url;//二维码链接
    private String mweb_url;//支付跳转链接	(h5支付返回)

    public String getMweb_url() {
        return mweb_url;
    }

    public void setMweb_url(String mweb_url) {
        this.mweb_url = mweb_url;
    }

    public String getReturn_code() {
        return return_code;
    }

    public void setReturn_code(String return_code) {
        this.return_code = return_code;
    }

    public String getReturn_msg() {
        return return_msg;
    }

    public void setReturn_msg(String return_msg) {
        this.return_msg = return_msg;
    }

    public String getAppid() {
        return appid;
    }

    public void setAppid(String appid) {
        this.appid = appid;
    }

    public String getMch_id() {
        return mch_id;
    }

    public void setMch_id(String mch_id) {
        this.mch_id = mch_id;
    }

    public String getDevice_info() {
        return device_info;
    }

    public void setDevice_info(String device_info) {
        this.device_info = device_info;
    }

    public String getNonce_str() {
        return nonce_str;
    }

    public void setNonce_str(String nonce_str) {
        this.nonce_str = nonce_str;
    }

    public String getSign() {
        return sign;
    }

    public void setSign(String sign) {
        this.sign = sign;
    }

    public String getResult_code() {
        return result_code;
    }

    public void setResult_code(String result_code) {
        this.result_code = result_code;
    }

    public String getErr_code_des() {
        return err_code_des;
    }

    public void setErr_code_des(String err_code_des) {
        this.err_code_des = err_code_des;
    }

    public String getTrade_type() {
        return trade_type;
    }

    public void setTrade_type(String trade_type) {
        this.trade_type = trade_type;
    }

    public String getPrepay_id() {
        return prepay_id;
    }

    public void setPrepay_id(String prepay_id) {
        this.prepay_id = prepay_id;
    }

    public String getCode_url() {
        return code_url;
    }

    public void setCode_url(String code_url) {
        this.code_url = code_url;
    }

    public String getErr_code() {
        return err_code;
    }

    public void setErr_code(String err_code) {
        this.err_code = err_code;
    }

    public UnifiedOrderResponse() {
    }

    public UnifiedOrderResponse(String return_code, String return_msg, String appid, String mch_id, String device_info, String nonce_str, String sign, String result_code, String err_code_des, String trade_type, String prepay_id, String code_url) {
        this.return_code = return_code;
        this.return_msg = return_msg;
        this.appid = appid;
        this.mch_id = mch_id;
        this.device_info = device_info;
        this.nonce_str = nonce_str;
        this.sign = sign;
        this.result_code = result_code;
        this.err_code_des = err_code_des;
        this.trade_type = trade_type;
        this.prepay_id = prepay_id;
        this.code_url = code_url;
    }

    @Override
    public String toString() {
        return "UnifiedOrderResponse{" +
                "return_code='" + return_code + '\'' +
                ", return_msg='" + return_msg + '\'' +
                ", appid='" + appid + '\'' +
                ", mch_id='" + mch_id + '\'' +
                ", device_info='" + device_info + '\'' +
                ", nonce_str='" + nonce_str + '\'' +
                ", sign='" + sign + '\'' +
                ", result_code='" + result_code + '\'' +
                ", err_code='" + err_code + '\'' +
                ", err_code_des='" + err_code_des + '\'' +
                ", trade_type='" + trade_type + '\'' +
                ", prepay_id='" + prepay_id + '\'' +
                ", code_url='" + code_url + '\'' +
                '}';
    }
}

新建一个微信支付的service


 public interface WechatPayService {
    //统一下单
    UnifiedOrderResponse unifiedOrder(UnifiedOrderRequest request, String key) throws UnsupportedEncodingException;
    
    }

接口类的实现

public class WechatPayServiceImpl implements WechatPayService {
    private static final Logger logger = LoggerFactory.getLogger(WechatPayServiceImpl.class);

		/**
		request 接口请求对象
		*/
    @Override
    public UnifiedOrderResponse unifiedOrder(UnifiedOrderRequest request, String key) {
        logger.info("WechatPayServiceImpl, unifiedOrder(), 返回值类型:UnifiedOrderResponse, request:{}", request);
        //String tmp = request.getBody();
        /** 获取签名 这里我的签名方式是MD5 WxConst.PAYKEY为你的密钥 */
        request.setSign(WxUtil.getSign(request,WxConst.PAYKEY));
        //request.setBody(tmp);
        String unifiedOrderRequestStr = XMLUtil.convertToXml(request);

        logger.info(unifiedOrderRequestStr);

        /** 设置https 请求*/
        HttpClient client = createSSLClientDefault();
        /** post请求*/
        HttpPost post = new HttpPost(WxConst.WXUNIFIEDORDERURL);
        /** 设置请求头*/
        post.setHeader("Content-Type", "application/xml");
        /** 转换实体参数*/
        StringEntity stringEntity = new StringEntity(unifiedOrderRequestStr, "UTF-8");
        /*stringEntity.setContentEncoding(new BasicHeader(HTTP.CONTENT_TYPE,
                "application/xml"));*/
        post.setEntity(stringEntity);

        try {
            HttpResponse httpResponse = client.execute(post);
            String resp = EntityUtils.toString(httpResponse.getEntity(), "UTF-8");
            UnifiedOrderResponse unifiedOrderResponse = (UnifiedOrderResponse) XMLUtil.convertXmlStrToObject(UnifiedOrderResponse.class, resp);
            logger.info(unifiedOrderResponse.toString());
            //成功
            if ("SUCCESS".equals(unifiedOrderResponse.getReturn_code()) && "SUCCESS".equals(unifiedOrderResponse.getResult_code())) {
                logger.info(unifiedOrderResponse.toString());
            }
            return unifiedOrderResponse;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
  }

!!!!微信支付签名的MD5加密的 方式通过参数拼接这里可以参考微信官方的参考文档 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3, 这个地方拼接的参数有个坑 (在做APP 调用支付的时候 我一直以为请求参数的商务id 是mch_id 其实 partnerid,要不然在 APP端调用支付会失败,但是自己在后端请求查询没问题。所以在app 调用支付的时候签名如果是后端返回的商务端id 字段是 partnerid )
在这里插入图片描述

public class WxUtil {
    public static String getSign(Object request,String key) {
        //logger.info("WechatPayServiceImpl, getSign(), 返回值类型:String, request:{}", request);
        String sign = "";
        Field[] fields = request.getClass().getDeclaredFields();
        int index = 0;
        int fieldNum = 0;
        String[] signArray = new String[fields.length - 1];
        for (int i = 0; i < fields.length; i++) {
            try {
            /** 这里通过反射获得到请求的参数,通过参数拼接这里可以参考微信官方			 https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=4_3
            */
                fields[i].setAccessible(true);
                if ("Sign".equals(fields[i].getName()) || fields[i].get(request) == null ||
                        "".equals(String.valueOf(fields[i].get(request)))) {
                    continue;
                }
             	
                if (fields[i].getName().equals("packAge")) {
                    signArray[index] = String.format("%s=%s", "package", String.valueOf(fields[i].get(request)));
                } else {
                    signArray[index] = String.format("%s=%s", fields[i].getName(), String.valueOf(fields[i].get(request)));
                }
                index++;
                fieldNum++;
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        if (fieldNum < signArray.length) {
            signArray = Arrays.copyOf(signArray, fieldNum);
        }
        Arrays.sort(signArray);
        //logger.info(toString(signArray) + String.format("&%s=%s", "key", WxConst.PAYKEY));
        sign = MD5Util.md5(toString(signArray) + String.format("&%s=%s", "key", key)).toUpperCase();
        return sign;
    }

    private static String toString(String[] a) {
        if (a == null)
            return "null";

        int iMax = a.length - 1;
        if (iMax == -1)
            return "";

        StringBuilder b = new StringBuilder();

        for (int i = 0; ; i++) {
            b.append(a[i]);
            if (i == iMax)
                return b.toString();
            b.append("&");
        }
    }
}
 
  • 测试调用
public class Test1{
	
	public void test (){
	   /** 给予统一支付下单 对象赋值*/
        /**
         * 小程序支付必须传参为
         *  @Param  [user.getOpenId() 用户标识] [WxConst.APPID3小程序ID] [WxConst.MACHID3 商户号] [nonceStr 随机字符串] [MD5 表示加密的方式] ,["原材料采购" 表示采购的名称]
         *  @Param  [body 商品描述 依照微信小程序规范上传] [purchaseOrder.getOrderNumber() 自己生成的订单号 ] [totalFee 订单总金额 单位为分]
         *  @Param [spbillCreateIp 调用微信支付API的机器IP 终端IP ] [notify_url 回调地址] [trade_type 交易类型  APP 表示APP 支付] [product_id 商品id 商品ID trade_type=NATIVE时(即扫码支付),此参数必传。此参数为二维码中包含的商品ID,商户自行定义。]
          */
	   UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest(WxConstMobile.APPID3, WxConstMobile.MACHID3,
                    null, nonceStr, null, "MD5", "原材料采购", null, "1",
                    purchaseOrder.getOrderNumber(), null, totalFee, spbillCreateIp, null, null,
                    null, WxConstMobile.WXNOTIFYURL, "APP", null, null, null);

            try {
            /** 调用统一下单接口*/
                UnifiedOrderResponse unifiedOrderResponse = wechatPayService.unifiedOrder(unifiedOrderRequest, WxConstMobile.PAYKEY3);
                /** 可以查看统一下单接口里面的参如果是成功 */
                if (!unifiedOrderResponse.getReturn_code().equals("SUCCESS")) {
                    return new BaseResponse<>(ErrorCode.ERROR_CUSTOM.getValue(), unifiedOrderResponse.getReturn_msg());
                }
                WechatUnifiedOrder wechatUnifiedOrder = new WechatUnifiedOrder(unifiedOrderResponse);
               	/** 对于返回的参数二次签名返回给APP 参数为上图所示的请求参数 */
                appPayResponse = new AppPayResponse(purchaseOrder.getWechatUnifiedOrder());
                appPayResponse.setSign(WxUtil.getSign(appPayResponse, WxConstMobile.PAYKEY3));
            } catch (Exception e) {
                e.printStackTrace();
            }
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值