【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)