您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

用H5调用支付微信公众号支付的解析

2025/4/8 18:43:12发布20次查看
这篇文章主要为大家详细介绍了微信公众号支付h5调用支付,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
最近项目需要微信支付,然后看了下微信公众号支付,虽然不难,但是细节还是需要注意的,用了大半天时间写了个demo,并且完整的测试了一下支付流程,下面分享一下微信公众号支付的经验。
一、配置公众号微信支付
需要我们配置微信公众号支付地址和测试白名单。
比如:支付js页面的地址为 http://www.xxx.com/shop/pay/
那此处配置www.xxx.com/shop/pay/
二、开发流程
借用微信公众号支付api(地址 http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=7_4),我们需要开发的为红色标记出的。如下:
三、向微信服务器端下订单
调用统一下单接口,这样就能获取微信支付的prepay_id(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_1)。
在调用该接口前有几个字段是h5支付必须填写的openid
3.1 获取openid
可以通过网页授权形式(http://mp.weixin.qq.com/wiki/17/c0f37d5704f0b64713d5d2c37b468d75.html)
在微信中发送如下链接
https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx520c15f417810387&redirect_uri=要跳转的下订单的url&response_type=code&scope=snsapi_base&state=123#wechat_redirect
3.2 后台支付
代码如下,包含预处理订单,支付订单等接口。
package org.andy.controller; import java.io.bytearrayinputstream; import java.io.ioexception; import java.io.inputstream; import java.io.unsupportedencodingexception; import java.util.date; import java.util.hashmap; import java.util.iterator; import java.util.map; import java.util.map.entry; import java.util.random; import javax.servlet.servletinputstream; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.apache.commons.codec.digest.digestutils; import org.springframework.stereotype.controller; import org.springframework.web.bind.annotation.requestmapping; import org.xmlpull.v1.xmlpullparser; import org.xmlpull.v1.xmlpullparserexception; import org.xmlpull.v1.xmlpullparserfactory; import com.fasterxml.jackson.databind.jsonnode; import com.gson.oauth.oauth; import com.gson.oauth.pay; import com.gson.util.httpkit; import com.gson.util.tools; import org.andy.util.datetimeutil; import org.andy.util.jsonutil; import org.andy.util.sessionutil; import org.andy.util.webutil; @controller @requestmapping("/pay") public class wxpaycontroller { @requestmapping(value = "wxprepay") public void jspay(httpservletrequest request, httpservletresponse response, string callback) throws exception { // 获取openid string openid = sessionutil.getatt(request, "openid"); if (openid == null) { openid = getuseropenid(request); } string appid = "wx16691fcb0523c1a4"; string partnerid = "22223670"; string paternerkey = "fjfjfjfjf1234567fffffffff1234567"; string out_trade_no = gettradeno(); map<string, string> paramap = new hashmap<string, string>(); paramap.put("appid", appid); paramap.put("attach", "测试支付"); paramap.put("body", "测试购买beacon支付"); paramap.put("mch_id", partnerid); paramap.put("nonce_str", create_nonce_str()); paramap.put("openid", openid); paramap.put("out_trade_no", out_trade_no); paramap.put("spbill_create_ip", getaddrip(request)); paramap.put("total_fee", "1"); paramap.put("trade_type", "jsapi"); paramap.put("notify_url", "http://www.xxx.co/wxpay/pay/apppay_notify.shtml"); string sign = getsign(paramap, paternerkey); paramap.put("sign", sign); // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder string url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; string xml = arraytoxml(paramap, false); string xmlstr = httpkit.post(url, xml); // 预付商品id string prepay_id = ""; if (xmlstr.indexof("success") != -1) { map<string, string> map = doxmlparse(xmlstr); prepay_id = (string) map.get("prepay_id"); } map<string, string> paymap = new hashmap<string, string>(); paymap.put("appid", appid); paymap.put("timestamp", create_timestamp()); paymap.put("noncestr", create_nonce_str()); paymap.put("signtype", "md5"); paymap.put("package", "prepay_id=" + prepay_id); string paysign = getsign(paymap, paternerkey); paymap.put("pg", prepay_id); paymap.put("paysign", paysign); webutil.response(response, webutil.packjsonp(callback, jsonutil.warpjsonnoderesponse(jsonutil.objecttojsonnode(paymap)).tostring())); } @requestmapping(value = "apppay") public void apppay(httpservletrequest request, httpservletresponse response, string body, string detail, string total_fee, string spbill_create_ip, string notify_url, string trade_type, string callback) throws exception { string appid = "wx16691fcb0523c1a4"; string partnerid = "22223670"; string paternerkey = "fjfjfjfjf1234567fffffffff1234567"; string out_trade_no = gettradeno(); map<string, string> paramap = new hashmap<string, string>(); paramap.put("appid", appid); paramap.put("body", body); paramap.put("mch_id", partnerid); paramap.put("nonce_str", create_nonce_str()); paramap.put("out_trade_no", out_trade_no); paramap.put("spbill_create_ip", spbill_create_ip); paramap.put("total_fee", total_fee); paramap.put("trade_type", trade_type); paramap.put("notify_url", notify_url); string sign = getsign(paramap, paternerkey); paramap.put("sign", sign); // 统一下单 https://api.mch.weixin.qq.com/pay/unifiedorder string url = "https://api.mch.weixin.qq.com/pay/unifiedorder"; string xml = arraytoxml(paramap, false); string xmlstr = httpkit.post(url, xml); // 预付商品id string prepay_id = ""; map<string, string> map = doxmlparse(xmlstr); if (xmlstr.indexof("success") != -1) { prepay_id = (string) map.get("prepay_id"); } string result_code = map.get("result_code"); string err_code_des = map.get("err_code_des"); map<string, string> paymap = new hashmap<string, string>(); paymap.put("appid", appid); paymap.put("partnerid", partnerid); paymap.put("prepayid", prepay_id); paymap.put("package", "sign=wxpay"); paymap.put("noncestr", create_nonce_str()); paymap.put("timestamp", create_timestamp()); string paysign = getsign(paymap, paternerkey); paymap.put("sign", paysign); paymap.put("result_code", result_code); paymap.put("err_code_des", err_code_des); webutil.response(response, webutil.packjsonp(callback, jsonutil.warpjsonnoderesponse(jsonutil.objecttojsonnode(paymap)).tostring())); } @requestmapping("/apppay_notify") public void apppaynotify(httpservletrequest request, httpservletresponse response) throws exception{ //string xml = "<xml><appid><![cdata[wxb4dc385f953b356e]]></appid><bank_type><![cdata[ccb_credit]]></bank_type><cash_fee><![cdata[1]]></cash_fee><fee_type><![cdata[cny]]></fee_type><is_subscribe><![cdata[y]]></is_subscribe><mch_id><![cdata[1228442802]]></mch_id><nonce_str><![cdata[1002477130]]></nonce_str><openid><![cdata[o-hreujzrr3momvv990vdfnq8x4k]]></openid><out_trade_no><![cdata[1000000000051249]]></out_trade_no><result_code><![cdata[success]]></result_code><return_code><![cdata[success]]></return_code><sign><![cdata[1269e03e43f2b8c388a414edae185cee]]></sign><time_end><![cdata[20150324100405]]></time_end><total_fee>1</total_fee><trade_type><![cdata[jsapi]]></trade_type><transaction_id><![cdata[1009530574201503240036299496]]></transaction_id></xml>"; response.setcharacterencoding("utf-8"); response.setcontenttype("text/xml"); servletinputstream in = request.getinputstream(); string xmlmsg = tools.inputstream2string(in); map<string, string> map = doxmlparse(xmlmsg); string return_code = map.get("return_code"); string return_msg = map.get("return_msg"); map = new hashmap<string, string>(); map.put("return_code", return_code); map.put("return_msg", return_msg); //响应xml string resxml = arraytoxml(map, true); response.getwriter().write(resxml); } @requestmapping("/orderquery.do") public void orderquery(httpservletrequest request, httpservletresponse response, string transaction_id, string out_trade_no, string callback) throws exception{ string url = "https://api.mch.weixin.qq.com/pay/orderquery"; string appid = "wx16691fcb0523c1a4"; string partnerid = "22223670"; string paternerkey = "fjfjfjfjf1234567fffffffff1234567"; map<string, string> map = new hashmap<string, string>(); map.put("appid", appid); map.put("mch_id", partnerid); if(transaction_id != null && !transaction_id.equals("")){ map.put("transaction_id", transaction_id); }else { map.put("out_trade_no", out_trade_no); } map.put("nonce_str", create_nonce_str()); string paysign = getsign(map, paternerkey); map.put("sign", paysign); string xml = arraytoxml(map, false); string xmlstr = httpkit.post(url, xml); map<string, string> ordermap = doxmlparse(xmlstr); webutil.response(response, webutil.packjsonp(callback, jsonutil.warpjsonnoderesponse(jsonutil.objecttojsonnode(ordermap)).tostring())); } /** * map转成xml * * @param arr * @return */ public string arraytoxml(map<string, string> parm, boolean isaddcdata) { stringbuffer strbuff = new stringbuffer(<xml>); if (parm != null ) { for (entry<string, string> entry : parm.entryset()) { strbuff.append("<").append(entry.getkey()).append(">"); if (isaddcdata) { strbuff.append(<![cdata[).append(entry.getvalue()).append(]]>); }else { strbuff.append(entry.getvalue()); } strbuff.append("<").append(entry.getkey()).append(">"); } } return strbuff.append(</xml>).tostring(); } // 获取openid private string getuseropenid(httpservletrequest request) throws exception { string code = request.getparameter("code"); if (code == null) { string openid = request.getparameter("openid"); return openid; } oauth o = new oauth(); string token = o.gettoken(code); jsonnode node = jsonutil.stringtojsonnode(token); string openid = node.get("openid").astext(); return openid; } private string create_nonce_str() { string chars = "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz0123456789"; string res = ""; for (int i = 0; i < 16; i++) { random rd = new random(); res += chars.charat(rd.nextint(chars.length() - 1)); } return res; } private string getaddrip(httpservletrequest request){ return request.getremoteaddr(); } private string create_timestamp() { return long.tostring(system.currenttimemillis() / 1000); } private string gettradeno(){ string timestamp = datetimeutil.formatdate(new date(), datetimeutil.datetime_pattern); return "hzno" + timestamp; } private string getsign(map<string, string> params, string paternerkey ) throws unsupportedencodingexception { string string1 = pay.createsign(params, false); string stringsigntemp = string1 + "&key=" + paternerkey; string signvalue = digestutils.md5hex(stringsigntemp).touppercase(); return signvalue; } private map<string, string> doxmlparse(string xml) throws xmlpullparserexception, ioexception { inputstream inputstream = new bytearrayinputstream(xml.getbytes()); map<string, string> map = null; xmlpullparser pullparser = xmlpullparserfactory.newinstance() .newpullparser(); pullparser.setinput(inputstream, "utf-8"); // 为xml设置要解析的xml数据 int eventtype = pullparser.geteventtype(); while (eventtype != xmlpullparser.end_document) { switch (eventtype) { case xmlpullparser.start_document: map = new hashmap<string, string>(); break; case xmlpullparser.start_tag: string key = pullparser.getname(); if (key.equals("xml")) break; string value = pullparser.nexttext(); map.put(key, value); break; case xmlpullparser.end_tag: break; } eventtype = pullparser.next(); } return map; } }
wxprepay.shtm接口是预处理订单接口向微信服务器下订单。
apppay.shtml接口是支付接口。
apppay_notify.shtml接口是微信支付后异步通知结果接口。
orderquery.shtml接口是订单查询接口
3.3、涉及到的工具类
sessionutil.java工具类
package org.andy.util; import javax.servlet.http.httpservletrequest; public class sessionutil { public static void addatt(httpservletrequest request, string key, object value){ request.getsession().setattribute(key, value); } public static void removeatt(httpservletrequest request, string key){ request.getsession().removeattribute(key); } public static string getatt(httpservletrequest request, string key){ return (string)request.getsession().getattribute(key); } public static object getattobj(httpservletrequest request, string key){ return request.getsession().getattribute(key); } public static string optatt(httpservletrequest request, string key, string value){ string r = (string)request.getsession().getattribute(key); if (r == null){ r = value; } return r; } }
httpkit 网络请求工具类
/** * https 请求 微信为https的请求 * * @author andy * @date 2015-10-9 下午2:40:19 */ public class httpkit { private static final string default_charset = "utf-8"; /** * @return 返回类型: * @throws ioexception * @throws unsupportedencodingexception * @throws nosuchproviderexception * @throws nosuchalgorithmexception * @throws keymanagementexception * @description 功能描述: get 请求 */ public static string get(string url, map<string, string> params, map<string, string> headers) throws ioexception, executionexception, interruptedexception { asynchttpclient http = new asynchttpclient(); asynchttpclient.boundrequestbuilder builder = http.prepareget(url); builder.setbodyencoding(default_charset); if (params != null && !params.isempty()) { set<string> keys = params.keyset(); for (string key : keys) { builder.addqueryparameter(key, params.get(key)); } } if (headers != null && !headers.isempty()) { set<string> keys = headers.keyset(); for (string key : keys) { builder.addheader(key, params.get(key)); } } future<response> f = builder.execute(); string body = f.get().getresponsebody(default_charset); http.close(); return body; } /** * @return 返回类型: * @throws ioexception * @throws unsupportedencodingexception * @throws nosuchproviderexception * @throws nosuchalgorithmexception * @throws keymanagementexception * @description 功能描述: get 请求 */ public static string get(string url) throws keymanagementexception, nosuchalgorithmexception, nosuchproviderexception, unsupportedencodingexception, ioexception, executionexception, interruptedexception { return get(url, null); } /** * @return 返回类型: * @throws ioexception * @throws nosuchproviderexception * @throws nosuchalgorithmexception * @throws keymanagementexception * @throws unsupportedencodingexception * @description 功能描述: get 请求 */ public static string get(string url, map<string, string> params) throws keymanagementexception, nosuchalgorithmexception, nosuchproviderexception, unsupportedencodingexception, ioexception, executionexception, interruptedexception { return get(url, params, null); } /** * @return 返回类型: * @throws ioexception * @throws nosuchproviderexception * @throws nosuchalgorithmexception * @throws keymanagementexception * @description 功能描述: post 请求 */ public static string post(string url, map<string, string> params) throws ioexception, executionexception, interruptedexception { asynchttpclient http = new asynchttpclient(); asynchttpclient.boundrequestbuilder builder = http.preparepost(url); builder.setbodyencoding(default_charset); if (params != null && !params.isempty()) { set<string> keys = params.keyset(); for (string key : keys) { builder.addparameter(key, params.get(key)); } } future<response> f = builder.execute(); string body = f.get().getresponsebody(default_charset); http.close(); return body; } public static string post(string url, string s) throws ioexception, executionexception, interruptedexception { asynchttpclient http = new asynchttpclient(); asynchttpclient.boundrequestbuilder builder = http.preparepost(url); builder.setbodyencoding(default_charset); builder.setbody(s); future<response> f = builder.execute(); string body = f.get().getresponsebody(default_charset); http.close(); return body; } }
支付工具类pay.java
/** * 支付相关方法 * @author andy * */ public class pay { // 发货通知接口 private static final string delivernotify_url = "https://api.weixin.qq.com/pay/delivernotify?access_token="; /** * 参与 paysign 签名的字段包括:appid、timestamp、noncestr、package 以及 appkey。 * 这里 signtype 并不参与签名微信的package参数 * @param params * @return * @throws unsupportedencodingexception */ public static string getpackage(map<string, string> params) throws unsupportedencodingexception { string partnerkey = confkit.get("partnerkey"); string partnerid = confkit.get("partnerid"); string notifyurl = confkit.get("notify_url"); // 公共参数 params.put("bank_type", "wx"); params.put("attach", "yongle"); params.put("partner", partnerid); params.put("notify_url", notifyurl); params.put("input_charset", "utf-8"); return packagesign(params, partnerkey); } /** * 构造签名 * @param params * @param encode * @return * @throws unsupportedencodingexception */ public static string createsign(map<string, string> params, boolean encode) throws unsupportedencodingexception { set<string> keysset = params.keyset(); object[] keys = keysset.toarray(); arrays.sort(keys); stringbuffer temp = new stringbuffer(); boolean first = true; for (object key : keys) { if (first) { first = false; } else { temp.append("&"); } temp.append(key).append("="); object value = params.get(key); string valuestring = ""; if (null != value) { valuestring = value.tostring(); } if (encode) { temp.append(urlencoder.encode(valuestring, "utf-8")); } else { temp.append(valuestring); } } return temp.tostring(); } /** * @param params * @param paternerkey * @return * @throws unsupportedencodingexception */ private static string packagesign(map<string, string> params, string paternerkey) throws unsupportedencodingexception { string string1 = createsign(params, false); string stringsigntemp = string1 + "&key=" + paternerkey; string signvalue = digestutils.md5hex(stringsigntemp).touppercase(); string string2 = createsign(params, true); return string2 + "&sign=" + signvalue; } /** * 支付签名 * @param timestamp * @param noncestr * @param packages * @return * @throws unsupportedencodingexception */ public static string paysign(string timestamp, string noncestr,string packages) throws unsupportedencodingexception { map<string, string> paras = new hashmap<string, string>(); paras.put("appid", confkit.get("appid")); paras.put("timestamp", timestamp); paras.put("noncestr", noncestr); paras.put("package", packages); paras.put("appkey", confkit.get("paysignkey")); // appid、timestamp、noncestr、package 以及 appkey。 string string1 = createsign(paras, false); string paysign = digestutils.shahex(string1); return paysign; } /** * 支付回调校验签名 * @param timestamp * @param noncestr * @param openid * @param issubscribe * @param appsignature * @return * @throws unsupportedencodingexception */ public static boolean verifysign(long timestamp, string noncestr, string openid, int issubscribe, string appsignature) throws unsupportedencodingexception { map<string, string> paras = new hashmap<string, string>(); paras.put("appid", confkit.get("appid")); paras.put("appkey", confkit.get("paysignkey")); paras.put("timestamp", string.valueof(timestamp)); paras.put("noncestr", noncestr); paras.put("openid", openid); paras.put("issubscribe", string.valueof(issubscribe)); // appid、appkey、productid、timestamp、noncestr、openid、issubscribe string string1 = createsign(paras, false); string paysign = digestutils.shahex(string1); return paysign.equalsignorecase(appsignature); } /** * 发货通知签名 * @param paras * @return * @throws unsupportedencodingexception * * @参数 appid、appkey、openid、transid、out_trade_no、deliver_timestamp、deliver_status、deliver_msg; */ private static string deliversign(map<string, string> paras) throws unsupportedencodingexception { paras.put("appkey", confkit.get("paysignkey")); string string1 = createsign(paras, false); string paysign = digestutils.shahex(string1); return paysign; } /** * 发货通知 * @param access_token * @param openid * @param transid * @param out_trade_no * @return * @throws ioexception * @throws nosuchproviderexception * @throws nosuchalgorithmexception * @throws keymanagementexception * @throws interruptedexception * @throws executionexception */ public static boolean delivernotify(string access_token, string openid, string transid, string out_trade_no) throws ioexception, executionexception, interruptedexception { map<string, string> paras = new hashmap<string, string>(); paras.put("appid", confkit.get("appid")); paras.put("openid", openid); paras.put("transid", transid); paras.put("out_trade_no", out_trade_no); paras.put("deliver_timestamp", (system.currenttimemillis() / 1000) + ""); paras.put("deliver_status", "1"); paras.put("deliver_msg", "ok"); // 签名 string app_signature = deliversign(paras); paras.put("app_signature", app_signature); paras.put("sign_method", "sha1"); string json = httpkit.post(delivernotify_url.concat(access_token), jsonobject.tojsonstring(paras)); if (stringutils.isnotblank(json)) { jsonobject object = jsonobject.parseobject(json); if (object.containskey("errcode")) { int errcode = object.getintvalue("errcode"); return errcode == 0; } } return false; } }
流转化tools.java工具类
public final class tools { public static final string inputstream2string(inputstream in) throws unsupportedencodingexception, ioexception{ if(in == null) return ""; stringbuffer out = new stringbuffer(); byte[] b = new byte[4096]; for (int n; (n = in.read(b)) != -1;) { out.append(new string(b, 0, n, "utf-8")); } return out.tostring(); } public static final boolean checksignature(string token,string signature,string timestamp,string nonce){ list<string> params = new arraylist<string>(); params.add(token); params.add(timestamp); params.add(nonce); collections.sort(params,new comparator<string>() { @override public int compare(string o1, string o2) { return o1.compareto(o2); } }); string temp = params.get(0)+params.get(1)+params.get(2); return sha1.encode(temp).equals(signature); } }
相应前端数据工具webutil.java工具类
public class webutil { public static object getsessionattribute(httpservletrequest req, string key) { object ret = null; try { ret = req.getsession(false).getattribute(key); } catch (exception e) { } return ret; } public static void response(httpservletresponse response, string result) { try { response.setcontenttype("application/json;charset=utf-8"); response.getwriter().write(result); } catch (ioexception e) { e.printstacktrace(); } } public static void response(httpservletresponse response, responsemessage result) { try { response.setcontenttype("application/json;charset=utf-8"); response.getwriter().write(jsonutil.objecttojsonnode(result).tostring()); } catch (exception e) { e.printstacktrace(); } } public static string packjsonp(string callback, string json) { if (json == null) { json = ""; } if (callback == null || callback.isempty()) { return json; } return callback + "&&" + callback + '(' + json + ')'; } public static string packjsonp(string callback, responsemessage response) { string json = null; if (response == null) { json = ""; } else { json = jsonutil.objecttojsonnode(response).tostring(); } if (callback == null || callback.isempty()) { return json; } return callback + "&&" + callback + '(' + json + ')'; } }
json转换工具jsonutil.java
public class jsonutil { public static objectnode warpjsonnoderesponse(jsonnode obj){ objectnode objectnode=createobjectnode(); objectnode.put("code", 1); objectnode.put("response", obj); return objectnode; } public static jsonnode objecttojsonnode(object obj){ try { objectmapper objectmapper = new objectmapper(); string objjson=objectmapper.writevalueasstring(obj); jsonnode jsonnode = objectmapper.readtree(objjson); return jsonnode; } catch (jsonprocessingexception e) { e.printstacktrace(); } catch (ioexception e) { // todo auto-generated catch block e.printstacktrace(); } return null; } }
四、微信h5调起支付
这个url需要后台实现,其实现功能如下:
1、接受微信服务器端发送的支付结果。
2、向微信服务器发送支付结果
具体 参考微信aip(http://pay.weixin.qq.com/wiki/doc/api/index.php?chapter=9_7)
具体代码如下:
4.1、授权向后台发起生成统一下订单页面
wxrepay.jsp
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <% string path = request.getcontextpath(); string basepath = request.getscheme() + "://" + request.getservername() + ":" + request.getserverport() + path + "/"; long t = system.currenttimemillis(); %> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="format-detection" content="telephone=no" /> <title>微信公众号支付</title> <link href="../css/css.css?t=<%=t%>" rel="stylesheet" type="text/css"> </head> <body> <p class="index_box"> <p class="apply_name">商品</p> <p class="branch_con"> <ul> <li><span class="name">beacon 1分钱 1只</span></li> <li><span class="name">测试支付信息</span></li> </ul> <p class="cz_btn"><a href="javascript:reppay();" class="btn_1">确定购买</a></p> </p> </p> <script type="text/javascript" src="../js/common.js?t=<%=t%>"></script> <script type="text/javascript" > var code = urlparameter("code"); function reppay(){ ajaxutil({}, mainpath+"/pay/wxprepay.shtml?code=" + code, repay); } function repay(response){ var info = response; var url = "wxpay?appid=" + info.appid + "&timestamp=" +info.timestamp + "&noncestr=" + info.noncestr + "&pg=" +info.pg + "&signtype=" +info.signtype + "&paysign=" +info.paysign; window.location.href= url + "&showwxpaytitle=1"; } </script> </body> </html>
首先是请求服务端wxprepay.shml接口,后台向微信支付平台获取支付订单信息,返回前台,wxpay.jsp页面
4.2、确认支付页面
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <%@ taglib prefix="spring" uri="http://www.springframework.org/tags" %> <% string path = request.getcontextpath(); string basepath = request.getscheme() + "://" + request.getservername() + ":" + request.getserverport() + path + "/"; long t = system.currenttimemillis(); %> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" /> <meta name="apple-mobile-web-app-capable" content="yes" /> <meta name="apple-mobile-web-app-status-bar-style" content="black" /> <meta name="format-detection" content="telephone=no" /> <title>微信公众号支付</title> <link href="../css/css.css?t=<%=t%>" rel="stylesheet" type="text/css"> </head> <body> <p class="index_box"> <p class="apply_name">微信js支付测试</p> <p class="branch_con"> <ul> <li><span class="name">测试支付信息</span></li> </ul> <p class="cz_btn"><a href="javascript:pay();" class="btn_1">立即支付</a></p> </p> </p> <script type="text/javascript" src="../js/common.js?t=<%=t%>"></script> <script type="text/javascript"> var appid = urlparameter("appid"); var timestamp = urlparameter("timestamp"); var noncestr = urlparameter("noncestr"); var pg = urlparameter("pg"); var signtype = urlparameter("signtype"); var paysign = urlparameter("paysign"); function onbridgeready(){ weixinjsbridge.invoke( 'getbrandwcpayrequest', { "appid" : appid, //公众号名称,由商户传入 "timestamp": timestamp, //时间戳,自1970年以来的秒数 "noncestr" : noncestr, //随机串 "package" : "prepay_id=" + pg, "signtype" : signtype, //微信签名方式: "paysign" : paysign //微信签名 }, function(res){ if(res.err_msg == "get_brand_wcpay_request:ok" ) { alert("支付成功"); } // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回 ok,但并不保证它绝对可靠。 } ); } function pay(){ if (typeof weixinjsbridge == "undefined"){ if( document.addeventlistener ){ document.addeventlistener('weixinjsbridgeready', onbridgeready, false); }else if (document.attachevent){ document.attachevent('weixinjsbridgeready', onbridgeready); document.attachevent('onweixinjsbridgeready', onbridgeready); } }else{ onbridgeready(); } } </script> </body> </html>
4.2、前台涉及到的工具类
javascript工具类common.js,样式css.css就不贴了没意义。
var path="wxpay"; var mainpath = "/wxpay"; var appid = "wx16691fcb0523c1a4"; var urlpre = "http://www.xxx.com/wxpay/page"; var urlhost = "http://www.xxx.com/"; $(document).ready(function(){ $(".refresher").click(function(){ refresh(); }); $("#goback").click(function(){ goback(); }); }); function popupmsg(msg){ alert(msg); } function printutilviaget(panel, requestdata, ajaxurl, printfunction){ $.ajax({ type: 'get', url: ajaxurl, data: requestdata, cache:false, datatype:"json", async: false, success: function(response) { if (response.code){ if (panel != null && panel.length > 0){ $(panel).html(""); if (printfunction != null) $(panel).html(printfunction(response.response)); } return true; } else { //alert(response.reason); } }, error: function(x, e) { //alert("error", x); }, complete: function(x) { //alert("call complete"); } }); return false; } function ajaxutilviaget(requestdata, ajaxurl, succfunction, failfunction){ $.ajax({ url: ajaxurl, type: "get", datatype: "json", cache:false, data: requestdata, async: false, success: function(response) { if (response.code){ if (succfunction != null) succfunction(response.response); } else { if (failfunction != null) failfunction(response.response); } }, error: function(x, e) { //alert("error", x); }, complete: function(x) { } }); return false; } function printutil(panel, requestdata, ajaxurl, printfunction, ajaxasync) { if (isempty(ajaxasync)) { ajaxasync = false; } $.ajax({ type : 'post', url : ajaxurl, data : requestdata, cache : false, datatype : "json", async : ajaxasync, success : function(response) { if (response.code) { if (panel != null && panel.length > 0) { $(panel).html(""); if (printfunction != null) $(panel).html(printfunction(response.response)); } return true; } else { // alert(response.reason); } }, error : function(x, e) { // alert("error", x); }, complete : function(x) { // alert("call complete"); } }); return false; } function appendutil(panel, requestdata, ajaxurl, printfunction, ajaxasync) { if (isempty(ajaxasync)) { ajaxasync = false; } $.ajax({ type : 'post', url : ajaxurl, data : requestdata, cache : false, datatype : "json", async : ajaxasync, success : function(response) { if (response.code) { if (panel != null && panel.length > 0) { if (printfunction != null) $(panel).append(printfunction(response.response)); } return true; } else { // alert(response.reason); } }, error : function(x, e) { // alert("error", x); }, complete : function(x) { // alert("call complete"); } }); return false; } function ajaxutilasync(requestdata, ajaxurl, succfunction, failfunction) { $.ajax({ url : ajaxurl, type : "post", datatype : "json", cache : false, data : requestdata, async : true, success : function(response) { if (typeof response.code == "number") { if (response.code > 0) { if (succfunction != null) succfunction(response.response); } else { if (failfunction != null) failfunction(response.response); } } else { if (response.result) { if (succfunction != null) succfunction(response.response); } else { if (failfunction != null) failfunction(response.response); } } }, error : function(x, e) { // alert("error", x); }, complete : function(x) { } }); return false; } function ajaxutil(requestdata, ajaxurl, succfunction, failfunction){ $.ajax({ url: ajaxurl, type: "post", datatype: "json", cache:false, data: requestdata, async: false, success: function(response) { if (typeof response.code == "number"){ if (response.code > 0){ if (succfunction != null) succfunction(response.response); } else { if (failfunction != null) failfunction(response.response); } } else { if (response.result){ if (succfunction != null) succfunction(response.response); } else { if (failfunction != null) failfunction(response.response); } } }, error: function(x, e) { //alert("error", x); }, complete: function(x) { } }); return false; } function loadselection(panel, requestdata, ajaxurl, itemname){ ajaxutil(requestdata, ajaxurl, function(response){ var list = response.list; for (var i = 0;i<list.length;i++){ $(panel).append("<option value='"+list[i][itemname]+"'>"+list[i][itemname]+"</option>"); } }, null); } function ajaxsubmitrefresh(formid) { var hideform = $(formid); var options = { datatype : "json", beforesubmit : function() { }, success : function(result) { if (result.result){ showmsg("提交成功"); } else { alert("提交失败!"); } }, error : function(result) { alert("提交失败!"); } }; hideform.ajaxsubmit(options); } function ajaxsubmitwithjump(formid, nextpage) { var hideform = $(formid); var options = { datatype : "json", beforesubmit : function() { }, success : function(result) { if (result.result){ alert("提交成功"); window.location.href = nextpage; } else { alert("提交失败!"); } }, error : function(result) { alert("提交失败!"); } }; hideform.ajaxsubmit(options); } function refresh(){ window.location.href = window.location.href; } function goback(){ history.go(-1); } function urlparameter(paras){ var url = location.href; var parastring = url.substring(url.indexof("?")+1,url.length).split("&"); var paraobj = {}; for (var i=0; j=parastring[i]; i++){ paraobj[j.substring(0,j.indexof("=")).tolowercase()] = j.substring(j.indexof("=")+1,j.length); } var returnvalue = paraobj[paras.tolowercase()]; if(typeof(returnvalue)=="undefined"){ return ""; }else{ return returnvalue; } } string.prototype.endwith=function(str){ if(str==null||str==""||this.length==0||str.length>this.length) return false; if(this.substring(this.length-str.length)==str) return true; else return false; return true; }; string.prototype.startwith=function(str){ if(str==null||str==""||this.length==0||str.length>this.length) return false; if(this.substr(0,str.length)==str) return true; else return false; return true; }; function getfileurl(sourceid) { var url = ""; if (navigator.useragent.indexof("msie")>=1) { // ie url = document.getelementbyid(sourceid).value; } else if(navigator.useragent.indexof("firefox")>0) { // firefox url = window.url.createobjecturl(document.getelementbyid(sourceid).files.item(0)); } else if(navigator.useragent.indexof("chrome")>0) { // chrome url = window.url.createobjecturl(document.getelementbyid(sourceid).files.item(0)); } return url; } function preimg(sourceid, targetid) { var url = getfileurl(sourceid); var imgpre = document.getelementbyid(targetid); imgpre.src = url; } function initwx(){ $.ajax({ url:mainpath+'/wechatjs.do', type:'post', datatype:'json', async: false, data: {url:location.href.split('#')[0]}, success:function(result){ console.log(result); var data=result['response']['map']; if(result['code']==1){ wx.config({ debug: false, appid:data['appid'], timestamp:data['timestamp'], noncestr:data['noncestr'], signature:data['signature'], jsapilist: ['onmenusharetimeline','onmenushareappmessage','getlocation', 'onmenushareqq', 'onmenushareweibo'] }); }else{ alert("fail to get code"); window.alert('fail'); }; } }); } var earth_radius = 6378137.0; //单位m var pi = math.pi; function getrad(d){ return d*pi/180.0; } function getgreatcircledistance(lat1,lng1,lat2,lng2){ var radlat1 = getrad(lat1); var radlat2 = getrad(lat2); var a = radlat1 - radlat2; var b = getrad(lng1) - getrad(lng2); var s = 2*math.asin(math.sqrt(math.pow(math.sin(a/2),2) + math.cos(radlat1)*math.cos(radlat2)*math.pow(math.sin(b/2),2))); s = s*earth_radius; s = math.round(s*10000)/10000.0; s = math.round(s); return s; } //对date的扩展,将 date 转化为指定格式的string //月(m)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符, //年(y)可以用 1-4 个占位符,毫秒(s)只能用 1 个占位符(是 1-3 位的数字) //例子: //(new date()).format("yyyy-mm-dd hh:mm:ss.s") ==> 2006-07-02 08:09:04.423 //(new date()).format("yyyy-m-d h:m:s.s") ==> 2006-7-2 8:9:4.18 date.prototype.format = function(fmt) { //author: meizz var o = { "m+" : this.getmonth()+1, //月份 "d+" : this.getdate(), //日 "h+" : this.gethours(), //小时 "m+" : this.getminutes(), //分 "s+" : this.getseconds(), //秒 "q+" : math.floor((this.getmonth()+3)/3), //季度 "s" : this.getmilliseconds() //毫秒 }; if(/(y+)/.test(fmt)) fmt=fmt.replace(regexp.$1, (this.getfullyear()+"").substr(4 - regexp.$1.length)); for(var k in o) if(new regexp("("+ k +")").test(fmt)) fmt = fmt.replace(regexp.$1, (regexp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); return fmt; }; //判断为空 function isempty(src){ if(("undefined" == typeof src) || (src == null) || ($.trim(src) == "") ){ return true; } return false; } //判断不为空 function notempty(src){ return !isempty(src); } //微信页面授权 snsapi_base方式 function wecharauto2burl(url) { return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + encodeuricomponent(url) + "&response_type=code&scope=snsapi_base&state=xybank#wechat_redirect"; } //页面授权针对snsapi_base方式授权的url function wecharauto2baseurl(url) { return wecharauto2burl(urlpre+url); } //页面授权针对snsapi_userinfo方式授权的url function wecharauto2userinfourl(url) { return "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + appid + "&redirect_uri=" + encodeuricomponent(urlpre+url) + "&response_type=code&scope=snsapi_userinfo&state=xybank#wechat_redirect"; } //微信分享 此方法需放在wx.ready中 function sharewechat(title, link, imgurl, desc){ wx.onmenusharetimeline({ title: title, // 分享标题 link: link, // 分享链接 imgurl: imgurl, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); //分享给朋友 wx.onmenushareappmessage({ title: title, // 分享标题 desc: desc, // 分享描述 link: link, // 分享链接 imgurl: imgurl, // 分享图标 type: 'link', // 分享类型,music、video或link,不填默认为link dataurl: '', // 如果type是music或video,则要提供数据链接,默认为空 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); //分享到qq wx.onmenushareqq({ title: title, // 分享标题 desc: desc, // 分享描述 link: link, // 分享链接 imgurl: imgurl, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); //分享到腾讯微博 wx.onmenushareweibo({ title: title, // 分享标题 desc: desc, // 分享描述 link: link, // 分享链接 imgurl: imgurl, // 分享图标 success: function () { // 用户确认分享后执行的回调函数 }, cancel: function () { // 用户取消分享后执行的回调函数 } }); }
五、支付结果
公众号调起效果如下:
支付成功后,微信服务器得到后台的notify通知后,会发微信说明支付信息,支付凭证如下:
后续会全部更新微信app支付,微信支付退款,微信企业向个人付款,支付宝相关支付。而且会上传全部代码到csdn资源下载处,尽请关注。
以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注!
以上就是用h5调用支付微信公众号支付的解析的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product