微信小程序支付
微信小程序支付流程:
先直接上代码
public Object devicePay(int userId,String deviceCode, double money,String time) {
ResultBean result = new ResultBean();
//判断设备是否存在
Device isExist = deviceDao.selectByDeviceCode(deviceCode);
if(isExist==null){
result.setStatus(false);
result.setCode(ResultEnums.DEVICE_NOT_EXIST.getCode());
result.setMsg(ResultEnums.DEVICE_NOT_EXIST.getMessage());
return result;
}
//判断用户是否存在
User user = userDao.getId((long)userId);
if(user==null){
result.setStatus(false);
result.setCode(ResultEnums.USER_NOT_EXIST.getCode());
result.setMsg(ResultEnums.USER_NOT_EXIST.getMessage());
return result;
}
String uuid = UUID.randomUUID().toString().substring(0,8);
String nowTime = DateUtils.getNowTimestamp();
//生成订单编号
String historyCode = nowTime+uuid;
DeviceHistory deviceHistory = new DeviceHistory(historyCode,deviceCode,userId,money,time,new DateUtils().getNowTime());
//新建一个订单
deviceHistoryDao.insertDeviceHistory(deviceHistory);
Map<String, String> map = new HashMap<String, String>();
map.put("appid",GlobalParas.APPID);//appid
map.put("mch_id",GlobalParas.MCH_ID);//商户号
map.put("nonce_str", WXPayUtil.generateNonceStr());//随机字符串
map.put("sign_type", WXPayConstants.SignType.MD5.toString());//签名类型
map.put("body",isExist.getDeviceName());//商品描述
map.put("out_trade_no",historyCode);//商户订单号,不能重复
map.put("trade_type","JSAPI");//小程序支付都填写 JSAPI
map.put("notify_url","https://xxxxx/pay/complete/"+historyCode);//通知地址,不能传递参数
int totalFee = (int) (money*100);
map.put("total_fee",String.valueOf(totalFee));//金额,以分为单位
map.put("openid",user.getOpenId());//小程序支付时,这个必须填,为用户唯一的编号 openid
String sign = "";
try {
//先进行签名
sign = WXPayUtil.generateSignature(map, GlobalParas.APIKEY);
map.put("sign",sign);
//转换为xml格式
String xml = WXPayUtil.generateSignedXml(map,GlobalParas.APIKEY);
//统一下单接口
String resultXml = HttpUtil.sendPostXml(GlobalParas.PAY_API_URL,xml);
Map<String, String> resultMap = WXPayUtil.xmlToMap(resultXml);
//判断是否请求成功
String RETURN_CODE = "return_code";
String return_code = null;
if (resultMap.containsKey(RETURN_CODE)) {
return_code = resultMap.get(RETURN_CODE);
}
String success = "SUCCESS";
if(!success.equals(return_code)){
result.setStatus(false);
result.setCode(ResultEnums.FAIL.getCode());
result.setMsg(ResultEnums.FAIL.getMessage());
return result;
}
//判断签名是否正确
if (!WXPayUtil.isSignatureValid(resultMap, GlobalParas.APIKEY, WXPayConstants.SignType.MD5)) {
result.setStatus(false);
result.setCode(ResultEnums.SIGN_FAIL.getCode());
result.setMsg(ResultEnums.SIGN_FAIL.getMessage());
return result;
}
//获取prepay_id(预付单信息)
String prepayId = resultMap.get("prepay_id");
String timeStamp = String.valueOf(WXPayUtil.getCurrentTimestamp());
String nonceStr = WXPayUtil.generateNonceStr();
String Package = "prepay_id="+prepayId;
Map paySignMap = new HashMap();
paySignMap.put("appId",GlobalParas.APPID);
paySignMap.put("timeStamp",timeStamp);//时间戳
paySignMap.put("nonceStr",nonceStr);//随机字符串
paySignMap.put("package",Package);//固定格式
paySignMap.put("signType","MD5");
//再次生成签名(含有预付单信息)
String paySign = WXPayUtil.generateSignature(paySignMap, GlobalParas.APIKEY);
JSONObject json = new JSONObject();
json.put("paySign",paySign);
json.put("timeStamp",timeStamp);
json.put("nonceStr",nonceStr);
json.put("Package",Package);
json.put("appId",GlobalParas.APPID);
//返回信息
result.setStatus(true);
result.setCode(ResultEnums.SELECT_SUCCESS.getCode());
result.setMsg(ResultEnums.SELECT_SUCCESS.getMessage());
result.setData(json);
} catch (Exception e) {
e.printStackTrace();
result.setStatus(false);
result.setCode(ResultEnums.UN_KNOW_ERROR.getCode());
result.setMsg(ResultEnums.UN_KNOW_ERROR.getMessage());
return result;
}
return result;
}
用户在小程序调起支付后发送到后台,发送到程序后台。后台再去调用微信支付的接口。先将所需传递的数据进行签名然后调用统一下单api,成功返回一个预付单编号(prepay_id)。将预付单编号与一些数据再次签名生成签名信息,返回小程序签名和一些数据。小程序前台调用下单接口。
统一下单api:https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1
里面有一些必须的参数:(小程序id,商户号,随机字符串,签名,商品描述,商户订单号,标价金额(以分为单位),通知地址(支付成功后微信后台会向这个地址发送信息,我们可以在这个接口实现更新订单状态),交易类型(小程序填写"JSAPI"))。参数需要为xml格式的。
其中随机字符串,签名我们可以利用微信提供的wxPayUtil
类中的方法
返回信息也是xml格式。我们可以利用wxPayUtils
里面的方法进行map与xml转换。判断返回信息中的return_code
是否为success
。然后获取prepay_id
。
再次签名。所需appid,时间戳,随机字符串,package等参数。将签名后的数据与参数一同返回前台。前台根据这些参数调起支付。
支付成功后会微信会请求我们第一次签名时设置的通知地址,我们可以在那个里面实现将订单状态修改为完成或其他业务逻辑。
微信sdk下载地址:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1