您的位置:首页 > 移动开发 > 微信开发

微信公众号支付接口网页开发示例

2017-01-22 00:00 260 查看
微信公众号支付是指在微信内嵌浏览器进入到公众号之后,点击电商页面的支付接口,他使用了微信内嵌浏览器的支持,开发步骤如下:
(1)首先开通企业公众号账户并且开通支付接口,详细步骤可以参考相关文档,这里不再细数,这一步问题不大,主要是企业账号等信息要设置准确,除了公众号还有企业商户号要设置。
(2)将用户openid传递到支付链接的参数中,例如:
<a href="/product/buy?id=productid&openid=user_openid">支付 </a>
(3)先写好支付成功后的微信回调函数处理程序,成功的话微信会访问配置好的通知url(notify_url),会尝试8次直到我们写回去success或者fail,示例代码如下:
@RequestMapping(value = "/wxpaycallback", method = { RequestMethod.POST,
RequestMethod.GET }, produces = { "application/json;charset=utf-8" })
public String weixinNotify(HttpServletRequest request,
HttpServletResponse response) {
try {
response.setCharacterEncoding("UTF-8");
InputStream inStream = request.getInputStream();
ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len = 0;
while ((len = inStream.read(buffer)) != -1) {
outSteam.write(buffer, 0, len);
}
outSteam.close();
inStream.close();
String resultStr = new String(outSteam.toByteArray(), "utf-8");
Map<String, String> resultMap =MessageUtil.parseXml(resultStr);
String out_trade_no = resultMap.get("out_trade_no");//订单号
String return_code = resultMap.get("return_code");
String mch_id=resultMap.get("mch_id");
if (return_code.contains("SUCCESS")) {
// 此处就是你的逻辑代码
if (mch_id.equals(WeixinUtil.MCH_ID)){
OrderLogic.finishOrder(out_trade_no);//处理该订单的状态
}
}
//返回消息给微信服务器
String retXml = "<xml> <return_code><![CDATA[SUCCESS]]></return_code> <return_msg><![CDATA[OK]]></return_msg></xml>";
PrintWriter out = response.getWriter();
out.print(retXml);
out.close();
} catch (Exception e) {
e.printStackTrace();
}
return "success";//这句话可以不用吧?
}

(4)Js端代码:
商品页面增加以下代码就会调用支付流程:
function onBridgeReady() {
var appId = $('#appId').val();// getUrlParam('appId');
var timeStamp = $('#timeStamp').val();// getUrlParam('timeStamp');
var nonceStr = $('#nonceStr').val();// getUrlParam('nonceStr');
var Package = $('#packageid').val();// getUrlParam('package');
var signType = $('#signType').val();// getUrlParam('signType');
var paySign = $('#paySign').val();// getUrlParam('paySign');
WeixinJSBridge.invoke('getBrandWCPayRequest', {
"appId" : appId, //公众号名称,由商户传入
"timeStamp" : timeStamp,// "1395712654", //时间戳,自1970年以来的秒数
"nonceStr" : nonceStr,// "e61463f8efa94090b1f366cccfbbb444", //随机串
"package" : Package,// "prepay_id=u802345jgfjsdfgsdg888",
"signType" : signType,// "MD5", //微信签名方式:
"paySign" : paySign,// "70EA570631E4BB79628FBCA90534C63FF7FADD89"
// //微信签名
}, function(res) { // 使用以上方式判断前端返回,微信团队郑重提示:res.err_msg将在用户支付成功后返回
// ok,但并不保证它绝对可靠。
// alert(res.err_msg);
if (res.err_msg == "get_brand_wcpay_request:ok") {
alert("success");
}
if (res.err_msg == "get_brand_wcpay_request:cancel") {
alert("cancel");
}
if (res.err_msg == "get_brand_wcpay_request:fail") {
alert("fail");
}
});
}

function callPay() {
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();
}
}

(5)还需要预先调用预下单接口才行,这部分代码暂时找不到了,后面补充。
写的不是很流畅,第一次写,感觉微信支付接口挺绕的,不如支付宝来的简洁。
附件:
微信用户在不同的公众号里时候openid值是不一样的,因此在支付的时候要先将用户的openid获取到传递给支付页面。获取openid一个方式是通过Oauth链接,就是说先进入Oauth地址,将H5页面url作为参数传递给Oauth链接,微信会回调这个url并将随机的code传给这个H5,通过code来查询微信api获取openid值。
public class WeixinLogic {
private static final Logger logger = LoggerFactory
.getLogger(WeixinLogic.class);
private static Gson gson = MyGlobal.gson();

/*
* 生成并记录短信验证码到数据库
*/
private static String genBindSmsCode(String mobile) {
String code = "";
DB db = MyMongo.getDB();
if (db != null) {
code = UserLogic.createRandom(true, 4);
DBCollection collection = db.getCollection("wxsmscode");
BasicDBObject cond = new BasicDBObject("mobile", mobile);
DBObject obj = collection.findOne(cond);
if (obj != null) {
DBObject doc = new BasicDBObject("$set", new BasicDBObject(
"code", code));
collection.update(cond, doc);
} else {
DBObject doc = new BasicDBObject().append("mobile", mobile)
.append("code", code);
collection.insert(doc);
}
}
return code;
}

/*
* 发送短信验证码
*/
public static void SendSmsCode(String mobile) {
String code = genBindSmsCode(mobile);
UserLogic.sendSmsCode(mobile, code);
}

/*
* 绑定公众号和手机号 成功返回true
*/
public static boolean bindwx(String openid, String mobile, String code) {
boolean ret = false;
if (!isMobileExist(mobile)) {
return false;
}
if (!checkSmsCode(mobile, code)) {
return false;
}
String old = getbindmobile(openid);
DB db = MyMongo.getDB();
if (db != null) {
DBCollection collection = db.getCollection("bindweixin");
if (!old.equals("")) {
collection.remove(new BasicDBObject("openid", openid));
}
try {
BindWeixin info = new BindWeixin();
DBObject doc = (DBObject) JSON.parse(gson.toJson(info));
collection.insert(doc);
return true;
} catch (Exception e) {
logger.error("bindwx" + e.getMessage());
return false;
}
}
return ret;
}

private static boolean isMobileExist(String mobile) {
boolean ret = true;

return ret;
}

/*
* 短信码是否正确
*/
private static boolean checkSmsCode(String mobile, String code) {
boolean ret = false;
DB db = MyMongo.getDB();
if (db != null) {
DBCollection collection = db.getCollection("wxsmscode");
BasicDBObject cond = new BasicDBObject("mobile", mobile).append(
"code", code);
DBObject obj = collection.findOne(cond);
if (obj != null) {
ret = true;
}
}
return ret;
}

/*
* 返回微信用户绑定的手机号
*/
public static String getbindmobile(String openid) {
String mobile = "";
DB db = MyMongo.getDB();
if (db != null) {
DBCollection collection = db.getCollection("bindweixin");
try {
DBObject obj = collection.findOne(new BasicDBObject("openid",
openid));
if (obj != null) {
BindWeixin info = gson.fromJson(obj.toString(),
BindWeixin.class);
mobile = info.mobile;
}
} catch (Exception e) {
logger.error("getbindmobile:" + e.getMessage());
}
}
return mobile;
}

public static void sendWXMonny(String re_openId, int money) {
String URL = "https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack";
String mch_id =WeixinUtil.MCH_ID;
SortedMap<Object, Object> parameters = new TreeMap<Object, Object>();
parameters.put("wxappid",WeixinUtil.APPID);
parameters.put("mch_id", mch_id);
String nonscr = UUID.randomUUID().toString().toUpperCase()
.replace("-", "");
parameters.put("nonce_str", nonscr);// 随机字符串
parameters.put("send_name", "中医管家");
String billno = createBillNo(mch_id, "01");
parameters.put("mch_billno",billno);
parameters.put("re_openid", re_openId);//我的微信openid: "oW9-5s8Aecs_teXlIuwTwNbLQyHk"
parameters.put("total_amount",money+"");
parameters.put("total_num", "1");
parameters.put("wishing", "中医管家");
parameters.put("client_ip", "127.0.0.1");
parameters.put("act_name", "测试红包用例");
parameters.put("remark", "中医管家");

// String sign = createSign("UTF-8", parameters);
// parameters.put("sign", sign);
sign(parameters);
&n
3ff0
bsp; String requestXML = getRequestXml(parameters);
String result = httpsRequest(URL, "POST", requestXML);
System.out.println("result:" + result);
}

public static String unifiedOrder(String openid,String trade_no,int fee,String doctorName){
//统一下单支付
String unified_url="https://api.mch.weixin.qq.com/pay/unifiedorder";
String notify_url="http://123.56.140.11/health/wxpaycallback";
// trade_no=UUID.randomUUID().toString().replace("-","");
try {
//生成sign签名
SortedMap<Object,Object> parameters = new TreeMap<Object,Object>();
parameters.put("appid",WeixinUtil.APPID);
parameters.put("attach", "中医管家");
parameters.put("body",doctorName);
parameters.put("mch_id",WeixinUtil.MCH_ID);
String nonscr =trade_no;// UUID.randomUUID().toString().toUpperCase().replace("-", "");
parameters.put("nonce_str", nonscr);
parameters.put("notify_url",notify_url);
parameters.put("out_trade_no", trade_no);
parameters.put("total_fee",fee+"");
parameters.put("trade_type", "JSAPI");
parameters.put("spbill_create_ip","127.0.0.1");
parameters.put("openid", openid);
parameters.put("device_info", "WEB");
sign(parameters);
String requestXML = getRequestXml(parameters);
String result =WeixinUtil. httpsRequest(unified_url, "POST", requestXML);
System.out.println("result:" + result);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return "";
}

private static String getRandomNum(int length) {
String val = "";
Random random = new Random();
for (int i = 0; i < length; i++) {
val += String.valueOf(random.nextInt(10));
}
return val;
}

public static String createBillNo(String mch_id, String userId) {
// 组成: mch_id+yyyymmdd+10位一天内不能重复的数字
// 10位一天内不能重复的数字实现方法如下:
// 因为每个用户绑定了userId,他们的userId不同,加上随机生成的(10-length(userId))可保证这10位数字不一样
Date dt = new Date();
SimpleDateFormat df = new SimpleDateFormat("yyyymmdd");
String nowTime = df.format(dt);
int length = 10 - userId.length();
return mch_id + nowTime + userId + getRandomNum(length);
}

public static void sign(SortedMap<Object, Object> params) {
String KEY =WeixinUtil.APIKEY;
Set<Entry<Object, Object>> entrys = params.entrySet();
Iterator<Entry<Object, Object>> it = entrys.iterator();
StringBuffer result = new StringBuffer();
while (it.hasNext()) {
Entry<Object, Object> entry = it.next();
result.append(entry.getKey()).append("=").append(entry.getValue())
.append("&");
}
result.append("key=").append(KEY);
params.put("sign", MD5Util.MD5Encode(result.toString(), "UTF-8")
.toUpperCase());
}
/*
* 发送红包接口示例
*/

public static String getRequestXml(SortedMap<Object, Object> parameters) {
StringBuffer sb = new StringBuffer();
sb.append("<xml>");
Set<Entry<Object, Object>> es = parameters.entrySet();
Iterator<Entry<Object, Object>> it = es.iterator();
while (it.hasNext()) {
@SuppressWarnings("rawtypes")
Map.Entry entry = (Map.Entry) it.next();
String k = (String) entry.getKey();
String v = String.valueOf(entry.getValue());
if ("attach".equalsIgnoreCase(k) || "body".equalsIgnoreCase(k)
|| "sign".equalsIgnoreCase(k)) {
sb.append("<" + k + ">" + "<![CDATA[" + v + "]]></" + k + ">");
} else {
sb.append("<" + k + ">" + v + "</" + k + ">");
}
}
sb.append("</xml>");
return sb.toString();
}

/**
* 发送https请求
*
* @param requestUrl
* 请求地址
* @param requestMethod
* 请求方式(GET、POST)
* @param outputStr
* 提交的数据
* @return 返回微信服务器响应的信息
*/
public static String httpsRequest(String requestUrl, String requestMethod,
String outputStr) {
try {
String result = "";
// // 创建SSLContext对象,并使用我们指定的信任管理器初始化
// TrustManager[] tm = { new MyX509TrustManager() };
// SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
// sslContext.init(null, tm, new java.security.SecureRandom());
// // 从上述SSLContext对象中得到SSLSocketFactory对象
// SSLSocketFactory ssf = sslContext.getSocketFactory();

// 指定读取证书格式为PKCS12
KeyStore keyStore = KeyStore.getInstance("PKCS12");
// 读取本机存放的PKCS12证书文件
FileInputStream instream = new FileInputStream(new File(
"/root/apiclient_cert.p12"));
try {
// 指定PKCS12的密码(商户ID)
keyStore.load(instream,WeixinUtil.MCH_ID.toCharArray());
} finally {
instream.close();
}
SSLContext sslcontext = SSLContexts.custom()
.loadKeyMaterial(keyStore, WeixinUtil.MCH_ID.toCharArray())
.build();
// 指定TLS版本
SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
sslcontext,
new String[] { "TLSv1" },
null,
SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);

CloseableHttpClient httpclient = HttpClients.custom()
.setSSLSocketFactory(sslsf).build();

//URL url = new URL(requestUrl);
HttpPost httpPost = new HttpPost(requestUrl);
StringEntity reqEntity = new StringEntity(outputStr, "utf-8"); // 如果此处编码不对,可能导致客户端签名跟微信的签名不一致
reqEntity.setContentType("application/x-www-form-urlencoded");
httpPost.setEntity(reqEntity);
CloseableHttpResponse response = httpclient.execute(httpPost);
try {
HttpEntity entity = response.getEntity();
if (entity != null) {
BufferedReader bufferedReader = new BufferedReader(
new InputStreamReader(entity.getContent(), "UTF-8"));
String text;
while ((text = bufferedReader.readLine()) != null) {
result += text;
}
}
EntityUtils.consume(entity);
} finally {
response.close();
}
return result;
// HttpsURLConnection conn =
// (HttpsURLConnection)httpclient.execute(httpPost);//
// url.openConnection();
// conn.setSSLSocketFactory(sslsf);
// conn.setDoOutput(true);
// conn.setDoInput(true);
// conn.setUseCaches(false);
// // 设置请求方式(GET/POST)
// conn.setRequestMethod(requestMethod);
// conn.setRequestProperty("content-type",
// "application/x-www-form-urlencoded");
// // 当outputStr不为null时向输出流写数据
// if (null != outputStr) {
// OutputStream outputStream = conn.getOutputStream();
&nb
3ff0
sp; // // 注意编码格式
// outputStream.write(outputStr.getBytes("UTF-8"));
// outputStream.close();
// }
// // 从输入流读取返回内容
// InputStream inputStream = conn.getInputStream();
// InputStreamReader inputStreamReader = new InputStreamReader(
// inputStream, "utf-8");
// BufferedReader bufferedReader = new BufferedReader(
// inputStreamReader);
// String str = null;
// StringBuffer buffer = new StringBuffer();
// while ((str = bufferedReader.readLine()) != null) {
// buffer.append(str);
// }
// // 释放资源
// bufferedReader.close();
// inputStreamReader.close();
// inputStream.close();
// inputStream = null;
// conn.disconnect();
// return buffer.toString();
} catch (ConnectException ce) {
logger.error("连接超时:{}", ce);
} catch (Exception e) {
logger.error("https请求异常:{}", e);
}
return null;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: