微信公众号支付开发步骤
程序员文章站
2023-12-22 16:28:46
...
开发流程:1 参照文档https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
A 准备好参数 传递给微信 调用微信统一下单接口生成预支付id
B j将微信返回的预支付id等参数传递给H5页面调用微信内存js方法
C 接受微信的异步通知 调用微信查询订单接口查看是否支付成功,成功后更新订单状态
1 前去认证的服务号申请微信支付,待申请通过后,前往微信商户平台登录 获取相应的配置参数
Appid 微信公众号appid
Mchid 商户号
Apikey API秘钥
获取之后填写在ConfigUtil中
/**
* 服务号相关信息
*/
public final static String APPID = "";//服务号的应用号
public final static String APP_SECRECT = "";//服务号的应用密码
public final static String TOKEN = "weixinCourse";//服务号的配置token
public final static String MCH_ID = "";//商户号
public final static String API_KEY = "";//API**
public final static String SIGN_TYPE = "MD5";//签名加密方式
public final static String CERT_PATH = "D:/apiclient_cert.p12";//微信支付证书存放路径地址
//微信支付统一接口的回调action
public final static String NOTIFY_URL = "http://tianba.tunnel.qydev.com/weixinpay_springMVC/pay/noticePay";
//微信支付成功支付后跳转的地址
public final static String SUCCESS_URL = "http://www.baidu.com";
//oauth2授权时回调action
public final static String REDIRECT_URI = "http://14.117.25.80:8016/GoMyTrip/a.jsp?port=8016";
/**
* 微信支付接口地址
*/
//微信支付统一接口(POST)
public final static String UNIFIED_ORDER_URL = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//微信退款接口(POST)
public final static String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";
//订单查询接口(POST)
public final static String CHECK_ORDER_URL = "https://api.mch.weixin.qq.com/pay/orderquery";
//关闭订单接口(POST)
public final static String CLOSE_ORDER_URL = "https://api.mch.weixin.qq.com/pay/closeorder";
//退款查询接口(POST)
public final static String CHECK_REFUND_URL = "https://api.mch.weixin.qq.com/pay/refundquery";
//对账单接口(POST)
public final static String DOWNLOAD_BILL_URL = "https://api.mch.weixin.qq.com/pay/downloadbill";
//短链接转换接口(POST)
public final static String SHORT_URL = "https://api.mch.weixin.qq.com/tools/shorturl";
//接口调用上报接口(POST)
public final static String REPORT_URL = "https://api.mch.weixin.qq.com/payitil/report";
2 开始写代码 开始搬砖
A 1 调用微信统一下单接口 得到预支付id
/**
*
* getPrepayId(调用微信统一下单接口,生成微信预支付id)
* @param totalFee 支付金额
* @param ipAddress ip地址
* @param orderNumber 订单号
* @param body 商品或支付单简要描述
* @param openid trade_type=JSAPI,此参数必传,用户在商户appid下的唯一标识
* @return
* @throws JDOMException
* @throws IOException
* @throws
* @author tianba
* @date 2016年6月27日 下午5:51:35
*/
public static Map<String, String> getPrepayId(String totalFee,String ipAddress,String orderNumber,String body,String openid) throws JDOMException, IOException{
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", ConfigUtil.APPID);
parameters.put("mch_id", ConfigUtil.MCH_ID);
parameters.put("nonce_str", CreateNoncestr());
parameters.put("body", body);
parameters.put("out_trade_no", orderNumber);
parameters.put("total_fee", totalFee);
parameters.put("spbill_create_ip",ipAddress);
parameters.put("notify_url", ConfigUtil.NOTIFY_URL);
parameters.put("trade_type", "JSAPI");
parameters.put("openid", openid);
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameters);
String result =CommonUtil.httpsRequest(ConfigUtil.UNIFIED_ORDER_URL, "POST", requestXML);
Map<String, String> map = XMLUtil.doXMLParse(result);//解析微信返回的信息,以Map形式存储便于取值
return map;
}
B 构造参数传递给H5页面
/**
*
* payOrder(调起微信支付)
* @param request
* @param totalFee //支付金额
* @param body //支付描述
* @return
* @throws
* @author tianba
* @date 2016年6月27日 下午6:45:26
*/
@RequestMapping(value="payOrder")
@ResponseBody
public String payOrder(HttpServletRequest request,double totalFee,String body){
String resultString=null;
BigDecimal fee = new BigDecimal(totalFee); // 微信支付参数以分为单位。
fee = fee.multiply(new BigDecimal(100));
String payFee=fee.longValue()+"";
//1 生成预支付id
String ipAddress=request.getRemoteAddr();
String orderNumber=System.currentTimeMillis()+new Random().nextInt(100)+"";
String openid="otASnt5zrkW8fgnY4MItTCil_Dpk"; //调用网页授权接口获取
try {
Map<String, String> map=PayCommonUtil.getPrepayId(payFee, ipAddress, orderNumber, body, openid);
String prepay_id=map.get("prepay_id");
//2 给H5页面传递参数 调起微信支付
resultString=PayCommonUtil.createPackageValue(prepay_id);
} catch (JDOMException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return resultString;
}
/**
*
* createPackageValue(调起支付)
* @param appid
* @param appKey
* @param prepay_id
* @return
* @throws
* @author tianba
* @date 2016年6月27日 下午5:31:11
*/
public static String createPackageValue(String prepay_id) {
SortedMap<Object,Object> params = new TreeMap<Object,Object>();
params.put("appId", ConfigUtil.APPID);
params.put("timeStamp", new Date().getTime()+"");
params.put("nonceStr", PayCommonUtil.CreateNoncestr());
params.put("package", "prepay_id="+prepay_id);
params.put("signType", ConfigUtil.SIGN_TYPE);
String paySign = PayCommonUtil.createSign("UTF-8", params);
params.put("packageValue", "prepay_id="+prepay_id); //这里用packageValue是预防package是关键字在js获取值出错
params.put("paySign", paySign); //paySign的生成规则和Sign的生成规则一致
params.put("sendUrl", ConfigUtil.SUCCESS_URL); //付款成功后跳转的页面
String json = JSONObject.toJSONString(params);
return json;
}
}
C H5支付页面代码
function payOrder(){
if(!isWeiXin()){
alert("请在微信浏览器中打开")
$("span").show();
return;
}else{
$("span").hide();
}
var totalFee=$("#totalFee").val();
var body=$("#body").val();
$.ajax({
type: "post",
url:basePath+"pay/payOrder" ,
data: {'totalFee':totalFee, 'body':body},
dataType: "json",
success: function(data){
WeixinJSBridge.invoke('getBrandWCPayRequest',{
"appId" : data.appId, //公众号名称,由商户传入
"timeStamp":data.timeStamp, //时间戳,自 1970 年以来的秒数
"nonceStr" : data.nonceStr, //随机串
"package" : data.packageValue, //<span style="font-family:微软雅黑;">商品包信息</span>
"signType" : data.signType, //微信签名方式:
"paySign" : data.paySign //微信签名
},function(res){
if(res.err_msg == "get_brand_wcpay_request:ok" ) {
window.location.href=data.sendUrl;
}else{
alert("fail");
// window.location.href="http://183.45.18.197:8016/wxweb/config/oauth!execute.action";
}
});
}
});
}
D 调用微信查询订单接口
/**
*
* queryWeiXinOrder(微信订单查询)
* @param orderNumber 订单号
* @return 当返回 return_code="SUCCESS"
* 和result_code="SUCCESS" 时 获取交易状态SUCCESS—支付成功
REFUND—转入退款
NOTPAY—未支付
CLOSED—已关闭
REVOKED—已撤销(刷卡支付)
USERPAYING--用户支付中
PAYERROR--支付失败(其他原因,如银行返回失败)
* @throws IOException
* @throws JDOMException
* @throws
* @author tianba
* @date 2016年6月30日 下午3:16:56
*/
public static Map<String, String> queryWeiXinOrder(String orderNumber) throws JDOMException, IOException{
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid", ConfigUtil.APPID);
parameters.put("mch_id", ConfigUtil.MCH_ID);
parameters.put("nonce_str", CreateNoncestr());
parameters.put("out_trade_no", orderNumber);
String sign = PayCommonUtil.createSign("UTF-8", parameters);
parameters.put("sign", sign);
String requestXML = PayCommonUtil.getRequestXml(parameters);
String result =CommonUtil.httpsRequest(ConfigUtil.CHECK_ORDER_URL, "POST", requestXML);
Map<String, String> map = XMLUtil.doXMLParse(result);//解析微信返回的信息,以Map形式存储便于取值
return map;
}
E 回调异步通知处理订单
/**
*
* updateOrderState(异步回调通知)
*
* @param request
* @throws
* @author tianba
* @date 2016年6月30日 下午3:35:12
*/
@RequestMapping(value="noticePay")
public void updateOrderState(HttpServletRequest request,HttpServletResponse response) {
try {
PrintWriter out= response.getWriter();
// xml请求解析
Map<String, Object> requestMap = CommonUtil.parseXml(request);
String orderNumber = (String) requestMap.get("out_trade_no");
if (orderNumber != null) {
// 调用微信查询订单接口,
Map<String, String> orderMap = PayCommonUtil.queryWeiXinOrder(orderNumber);
if (orderMap.get("return_code") != null&& orderMap.get("return_code").equalsIgnoreCase("SUCCESS")) {
if (orderMap.get("result_code") != null&& orderMap.get("result_code").equalsIgnoreCase("SUCCESS")) {
if (orderMap.get("trade_state") != null&& orderMap.get("trade_state").equalsIgnoreCase("SUCCESS")) {
// 支付成功。。。。开始更新你的订单状态吧
String resultXml="<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
out.println(resultXml);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意 支付目录配置