【JAVA版】微信支付方案一详解
【摘要】 在接入微信支付插件时,如果使用方案一完成,难点还是在getOrderId。这个方法的服务器端实现,还要多参考微信提供的接口文档。对接起来还是有很多小坑的,希望以下经验,能给您提供帮助。参考接入接口 : https://pay.weixin.qq.com/wiki/doc/api/index.html管理端后台的Java主体代码如下:/** * 微信支付获取预支付订单号 ...
在接入微信支付插件时,如果使用方案一完成,难点还是在getOrderId。这个方法的服务器端实现,还要多参考微信提供的接口文档。对接起来还是有很多小坑的,希望以下经验,能给您提供帮助。
参考接入接口 : https://pay.weixin.qq.com/wiki/doc/api/index.html
管理端后台的Java主体代码如下:
/** * 微信支付获取预支付订单号 * <ul> * <li>1、封装数据,进行预支付,获取统一下单的prepay_id</li> * <li>2、验证是否下单成功,成功后,将签名数据返回</li> * </ul> * @param request * @param response * @return * @author JiangZhongyan * @throws NoSuchAlgorithmException */ @SuppressWarnings("unchecked") @ResponseBody @RequestMapping(value = "wxpay-order-info") public String getPayOrderInfo(HttpServletRequest request, HttpServletResponse response) throws NoSuchAlgorithmException { String payType = request.getParameter("type"); String tradeNo = request.getParameter("tradeNo"); String totalFee = request.getParameter("totalFee"); // 封装微信支付申请参数对象,注意APP支付和微信公众号支付的参数差异 WxpayPreConfig preConfig = new WxpayPreConfig(tradeNo, totalFee, WxpayHelper.TRADE_TYPE_APP); preConfig.setNotify_url(prop.getWxNotifyUrl()); String secretKey = prop.getWxAppSecret(); preConfig.setTrade_type(WxpayHelper.TRADE_TYPE_APP); preConfig.setAppid(prop.getWxAppId()); preConfig.setMch_id(prop.getWxMchId()); // 预支付信息 Map<String, String> preInfo = new HashMap<>(BeanMap.create(preConfig)); preInfo.put("sign", WxpayHelper.getMD5Sign(preInfo, secretKey)); String resultStr = ClientUtils.sendPost(prop.getWxSendUri(), WxpayHelper.getRequestXml(preInfo), StringUtils.UTF8); // 统一下单结果,主要为了获取prepay_id JSONObject result = XmlUtils.getJSONFromXml(resultStr); // 检测是否下单成功以及签名是否正确 if (result.getString("return_code").equals("SUCCESS") && WxpayHelper.checkSign(result, secretKey)) { // 解析下单结果,并返回前台使用 WxpayConfig retConfig = new WxpayConfig(result.getString("prepay_id")); retConfig.setAppid(prop.getWxAppId()); retConfig.setPartnerid(prop.getWxMchId()); Map<String, String> info = new HashMap<>(BeanMap.create(retConfig)); info.put("package", "Sign=WXPay"); // 二次签名 info.put("sign", WxpayHelper.getMD5Sign(info, secretKey)); // 拼装返回前台信息 return JSONObject.fromObject(info).toString(); } return JSONObject.fromObject(new ErrorMsgBean(resultStr)).toString(); }
说明:
1)其中,WxpayPreConfig类的内容,参考接口文档,自己拼凑即可。
2)prop.getWxSendUri() = https://api.mch.weixin.qq.com/pay/unifiedorder
3)附上MD5签名方法,注意map的排序。
public static String getMD5Sign(Map<String, String> map, String key) throws NoSuchAlgorithmException { StringBuffer info = new StringBuffer(StringUtils.getSortedParam(map)); // 若有key if (!StringUtils.isNullOrEmpty(key)) { info.append("&key=" + key); } return StringUtils.MD5(info.toString()).toUpperCase(); }
说明:这里附上的代码,仅提供开发思路。可能不全。如果需要源代码者,再线下联系。可以提供相关代码。
如下为,正确统一下单之后,返回的结果数据:
【微信统一下单参数结果】 <xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg><appid><![CDATA[<你自己的>]]></appid><mch_id><![CDATA[<你自己的>]]></mch_id><nonce_str><![CDATA[LMvSZOBztoQzz13g]]></nonce_str><sign><![CDATA[<你自己的>]]></sign><result_code><![CDATA[SUCCESS]]></result_code><prepay_id><![CDATA[<你自己的>]]></prepay_id><trade_type><![CDATA[APP]]></trade_type></xml>
在APP一侧的JS代码中,对接如下:
/** * 微信支付 * 微信支付的最小单位是分 * 注意Number(price) * 100的冗余错误,加上parseInt修正 * parseInt(Number(price) * 100) * @param tradeNo 商户系统内部的订单号 * @param price 订单总金额,只能为整数,单位:分(¥) */ function execWxpay(tradeNo, price, desc) { var data = { tradeNo : tradeNo, totalFee : price, description : '支付订单' } ajax.post('app/wxpay-order-info.action', data, function(data) { if (!extApi.isNullObj(data)) { var wxPay = api.require('wxPay'); wxPay.payOrder({ apiKey : data.appid, orderId : data.prepayid, mchId : data.partnerid, nonceStr : data.noncestr, timeStamp : data.timestamp, package : 'Sign=WXPay', sign : data.sign }, function(ret, err) { if (!ret.status) { var msg = getWxRetErrorCodeMsg(err.code); extApi.alert(msg, '支付结果'); } if (ret.status) { closePayWin(); } }); } }); } /** * 微信支付失败时返回的错误码 * -2:用户取消 * -1:未知错误,可能的原因:签名错误、未注册APPID、项目设置APPID不正确、注册的APPID与设置的不匹配、其他异常等 * 1:apiKey值非法 */ function getWxRetErrorCodeMsg(code) { switch(code) { case '-2': return '用户取消'; case '1': return 'apiKey值非法'; default: return '未知错误'; } }
正确提交支付后,微信返回的支付成功数据串,示例如下:
【微信支付回调时的String参数】<xml><appid><![CDATA[<你自己的>]]></appid><bank_type><![CDATA[CFT]]></bank_type><cash_fee><![CDATA[1]]></cash_fee><fee_type><![CDATA[CNY]]></fee_type><is_subscribe><![CDATA[N]]></is_subscribe><mch_id><![CDATA[<你自己的>]]></mch_id><nonce_str><![CDATA[ps6Opmjk]]></nonce_str><openid><![CDATA[<你自己的>]]></openid><out_trade_no><![CDATA[20170904182528806]]></out_trade_no><result_code><![CDATA[SUCCESS]]></result_code><return_code><![CDATA[SUCCESS]]></return_code><sign><![CDATA[<你自己的>]]></sign><time_end><![CDATA[20170904182539]]></time_end><total_fee>1</total_fee><trade_type><![CDATA[APP]]></trade_type><transaction_id><![CDATA[4009082001201709040196726483]]></transaction_id></xml>
特别注意:
1)尤其是APP和微信公众号都有接入的项目,一定要注意二者之间的差异。主要在账号上,不能混用,否则支付会一直不成功。
2)在附件中,会携带主要的Java类方法。但可能还是会不全。
以上内容,希望对您有用。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)