完整demo 上传头像
因为没有用canvas所以并不会有图片旋转的问题。
在实际工作中遇到了上传头像的需求,刚开始做的时候发现社区里面都是零散的代码,都是在说原理的没有一个完整的功能,然后就自己写了这个功能和大家分享一下,下载下来放hbuilder里面运行就能看到效果了,有需要的可以拿去用。
打开该链接有效果图,可以看一下是不是想要的。
承接各种APP开发,插件集成及离线打包等业务 qq:37894663
承接各种APP开发,插件集成及离线打包等业务 qq:37894663
承接各种APP开发,插件集成及离线打包等业务 qq:37894663
【交流分享】原生js实现下拉刷新上拉加载,一套代码多端运行.经典APP案例,支持vue,流应用,兼容手机及PC浏览器
8月伊始,好东西与大家一起分享~
好久没有写东西了,这大半年都在忙公司的项目.永远也弄不完的需求; APP做好了,新的需求要把APP搬到微信端, 微信端好不容易改好了, 还要做一个版本发到PC官网; PC官网弄好了,接下来还得研究一下小程序,小程序还没整明白,新来的产品说要用vue优化一下项目~~(>_<)~~
挺感谢HBuilder提供的平台,让APP大部分代码能够迁移到其他平台;省了不少功夫;
然后有些组件就不好弄了,比如双webview的下拉刷新,上拉加载; 如果涉及到菜单切换,或者要刷新父webview的情况就比较复杂了;APP一套代码,微信端也弄一套,维护起来比较麻烦;
于是抽空用原生js实现了下拉刷新上拉加载,完美运用于android,ios,兼容手机及PC主流浏览器,一套代码多端运行.支持vue,流应用,
mescroll -- 精致的下拉刷新和上拉加载js框架 (JS framework for pull-refresh and pull-up-loading)
功能亮点 :
1.自动判断和提示列表无任何数据或无更多数据
2.支持监听列表滚动事件,无需手动判断处理列表的页码,时间等变量
3.可指定列表滚动到任何位置,附带平滑效果一键滚动到顶部或底部
4.可配置列表数据不满屏时,自动加载下一页
5.一个界面可支持多个下拉刷新,上拉加载
6.可临时锁定下拉刷新和上拉加载
7......
先看看
mescroll主流APP案例:
【仿淘宝 v6.8.0】APP的下拉刷新上拉加载
【仿京东 v6.1.0】APP的下拉刷新上拉加载
【仿贝贝 v6.0.0】APP的下拉刷新上拉加载
【仿新浪微博 v7.6.1】APP的下拉刷新上拉加载
【雅布力 v2.4.0】APP的下拉刷新上拉加载
快速入门 :
1 引用 mescroll.min.css , mescroll.min.js
2 拷贝以下布局结构:
<div id="mescroll" class="mescroll">
//列表内容,如:<ul>列表数据</ul> ...
</div>
3 创建MeScroll对象:
var mescroll = new MeScroll("mescroll", {
down: {
callback: downCallback //下拉刷新的回调
},
up: {
callback: upCallback //上拉加载回调,简写callback:function(page){upCallback(page);}
}
});
4 处理回调:
//下拉刷新的回调
function downCallback(){
$.ajax({
url: 'xxxxxx',
success: function(data){
//联网成功的回调,隐藏下拉刷新的状态;
mescroll.endSuccess();//无参
//设置数据
//setXxxx(data);//自行实现 TODO
},
error: function(data){
//联网失败的回调,隐藏下拉刷新的状态
mescroll.endErr();
}
});
}
//上拉加载的回调 page = {num:1, size:10}; num:当前页 从1开始, size:每页数据条数
function upCallback(page){
$.ajax({
url: 'xxxxxx?num='+ page.num +"&size="+ page.size,
success: function(data){
//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
//参数data.length:当前页的数据总数
//mescroll会根据data.length自动判断列表如果无任何数据,则提示空,显示empty配置的内容;
//列表如果无下一页数据,则提示无更多数据;
//如果不传data.length,则仅隐藏下拉刷新和上拉加载的状态.例如downCallback
mescroll.endSuccess(data.length);
//设置列表数据
//setListData(data);//自行实现 TODO
},
error: function(data){
//联网失败的回调,隐藏下拉刷新和上拉加载的状态
mescroll.endErr();
}
});
}
以上为mescroll最基本的用法,强烈建议您下载并查看 mescroll基础案例 , 发现mescroll更强大的功能 ~
基础案例一共5个, 每个案例3分钟, 一共花您15分钟;
这15分钟您将了解mescroll在不同情况下应如何快速配置 ~
磨刀不误砍柴工,心急吃不了热豆腐. 请静下心来体验与理解mescroll, 一定会让您事半功倍 ~
mescroll文档及案例:
https://github.com/mescroll/mescroll
8月伊始,好东西与大家一起分享,
如使用中有任何问题,可发帖提问@我; 或者发私信;
提问前最好能提供重现问题的案例~O(∩_∩)O谢谢
8月伊始,好东西与大家一起分享~
好久没有写东西了,这大半年都在忙公司的项目.永远也弄不完的需求; APP做好了,新的需求要把APP搬到微信端, 微信端好不容易改好了, 还要做一个版本发到PC官网; PC官网弄好了,接下来还得研究一下小程序,小程序还没整明白,新来的产品说要用vue优化一下项目~~(>_<)~~
挺感谢HBuilder提供的平台,让APP大部分代码能够迁移到其他平台;省了不少功夫;
然后有些组件就不好弄了,比如双webview的下拉刷新,上拉加载; 如果涉及到菜单切换,或者要刷新父webview的情况就比较复杂了;APP一套代码,微信端也弄一套,维护起来比较麻烦;
于是抽空用原生js实现了下拉刷新上拉加载,完美运用于android,ios,兼容手机及PC主流浏览器,一套代码多端运行.支持vue,流应用,
mescroll -- 精致的下拉刷新和上拉加载js框架 (JS framework for pull-refresh and pull-up-loading)
功能亮点 :
1.自动判断和提示列表无任何数据或无更多数据
2.支持监听列表滚动事件,无需手动判断处理列表的页码,时间等变量
3.可指定列表滚动到任何位置,附带平滑效果一键滚动到顶部或底部
4.可配置列表数据不满屏时,自动加载下一页
5.一个界面可支持多个下拉刷新,上拉加载
6.可临时锁定下拉刷新和上拉加载
7......
先看看
mescroll主流APP案例:
【仿淘宝 v6.8.0】APP的下拉刷新上拉加载
【仿京东 v6.1.0】APP的下拉刷新上拉加载
【仿贝贝 v6.0.0】APP的下拉刷新上拉加载
【仿新浪微博 v7.6.1】APP的下拉刷新上拉加载
【雅布力 v2.4.0】APP的下拉刷新上拉加载
快速入门 :
1 引用 mescroll.min.css , mescroll.min.js
2 拷贝以下布局结构:
<div id="mescroll" class="mescroll">
//列表内容,如:<ul>列表数据</ul> ...
</div>
3 创建MeScroll对象:
var mescroll = new MeScroll("mescroll", {
down: {
callback: downCallback //下拉刷新的回调
},
up: {
callback: upCallback //上拉加载回调,简写callback:function(page){upCallback(page);}
}
});
4 处理回调:
//下拉刷新的回调
function downCallback(){
$.ajax({
url: 'xxxxxx',
success: function(data){
//联网成功的回调,隐藏下拉刷新的状态;
mescroll.endSuccess();//无参
//设置数据
//setXxxx(data);//自行实现 TODO
},
error: function(data){
//联网失败的回调,隐藏下拉刷新的状态
mescroll.endErr();
}
});
}
//上拉加载的回调 page = {num:1, size:10}; num:当前页 从1开始, size:每页数据条数
function upCallback(page){
$.ajax({
url: 'xxxxxx?num='+ page.num +"&size="+ page.size,
success: function(data){
//联网成功的回调,隐藏下拉刷新和上拉加载的状态;
//参数data.length:当前页的数据总数
//mescroll会根据data.length自动判断列表如果无任何数据,则提示空,显示empty配置的内容;
//列表如果无下一页数据,则提示无更多数据;
//如果不传data.length,则仅隐藏下拉刷新和上拉加载的状态.例如downCallback
mescroll.endSuccess(data.length);
//设置列表数据
//setListData(data);//自行实现 TODO
},
error: function(data){
//联网失败的回调,隐藏下拉刷新和上拉加载的状态
mescroll.endErr();
}
});
}
以上为mescroll最基本的用法,强烈建议您下载并查看 mescroll基础案例 , 发现mescroll更强大的功能 ~
基础案例一共5个, 每个案例3分钟, 一共花您15分钟;
这15分钟您将了解mescroll在不同情况下应如何快速配置 ~
磨刀不误砍柴工,心急吃不了热豆腐. 请静下心来体验与理解mescroll, 一定会让您事半功倍 ~
mescroll文档及案例:
https://github.com/mescroll/mescroll
8月伊始,好东西与大家一起分享,
如使用中有任何问题,可发帖提问@我; 或者发私信;
提问前最好能提供重现问题的案例~O(∩_∩)O谢谢
Android获取Wifi名称
getWifiName = function() {
if(mui.os.android) {
var wifiManager, wifiInfo;
var Context = plus.android.importClass("android.content.Context");
var WifiManager = plus.android.importClass("android.net.wifi.WifiManager");
var WifiInfo = plus.android.importClass("android.net.wifi.WifiInfo");
wifiManager = plus.android.runtimeMainActivity().getSystemService(Context.WIFI_SERVICE);
wifiInfo = wifiManager.getConnectionInfo();
var ssid = wifiInfo.getSSID() || '';
if(ssid.length == 0) {
return null;
}
//一些手机上获取SSID是有值的,但是实际IP为空,真实为未连接
var i = parseInt(wifiInfo.getIpAddress());
var ipStr = (i & 0xFF) + "." +
((i >> 8) & 0xFF) + "." +
((i >> 16) & 0xFF) + "." +
(i >> 24 & 0xFF);
if(ipStr == "0.0.0.0") {
return null;
}
if(ssid != "<unknown ssid>" && ssid.toUpperCase() != "0X") {
return ssid.replace(/\"/g, "");
}
return null;
}
return null;
}; getWifiName = function() {
if(mui.os.android) {
var wifiManager, wifiInfo;
var Context = plus.android.importClass("android.content.Context");
var WifiManager = plus.android.importClass("android.net.wifi.WifiManager");
var WifiInfo = plus.android.importClass("android.net.wifi.WifiInfo");
wifiManager = plus.android.runtimeMainActivity().getSystemService(Context.WIFI_SERVICE);
wifiInfo = wifiManager.getConnectionInfo();
var ssid = wifiInfo.getSSID() || '';
if(ssid.length == 0) {
return null;
}
//一些手机上获取SSID是有值的,但是实际IP为空,真实为未连接
var i = parseInt(wifiInfo.getIpAddress());
var ipStr = (i & 0xFF) + "." +
((i >> 8) & 0xFF) + "." +
((i >> 16) & 0xFF) + "." +
(i >> 24 & 0xFF);
if(ipStr == "0.0.0.0") {
return null;
}
if(ssid != "<unknown ssid>" && ssid.toUpperCase() != "0X") {
return ssid.replace(/\"/g, "");
}
return null;
}
return null;
}; 收起阅读 »
子webview中使用地图
5+的demo中介绍了如何使用内置地图,方式是单webview,即延时初始化map,并调用webview的show函数。
当我想在tabbar的某个子页面(非首页)中使用地图时,我发现,如果子页面按5+的demo写(调用show),那么地图页会覆盖首页;如果不调用子webview的show函数,虽然不覆盖首页,但切换后,地图不显示。上述现象只出现在android上。
似乎地图只能在单webview下使用才合适。
经过大量测试,暂时找到了规避方法(不知道算不算解决方法,有人提过类似的问题,但不知道是不屑还是讳莫如深,没人回答),即在创建子webview后,在自己的plusready中调用hide函数。
plus.webview.currentWebview().hide();
注意:只能是自己的plusready,在父页面中创建子webview后,调用hide函数无效。
这种规避方法只是在目前官方没有解答的情况下使用,期待官方的正式解决方案或者说使用指南。
5+的demo中介绍了如何使用内置地图,方式是单webview,即延时初始化map,并调用webview的show函数。
当我想在tabbar的某个子页面(非首页)中使用地图时,我发现,如果子页面按5+的demo写(调用show),那么地图页会覆盖首页;如果不调用子webview的show函数,虽然不覆盖首页,但切换后,地图不显示。上述现象只出现在android上。
似乎地图只能在单webview下使用才合适。
经过大量测试,暂时找到了规避方法(不知道算不算解决方法,有人提过类似的问题,但不知道是不屑还是讳莫如深,没人回答),即在创建子webview后,在自己的plusready中调用hide函数。
plus.webview.currentWebview().hide();
注意:只能是自己的plusready,在父页面中创建子webview后,调用hide函数无效。
这种规避方法只是在目前官方没有解答的情况下使用,期待官方的正式解决方案或者说使用指南。
收起阅读 »h5+教程、mui教程、各类app开发实战教程更新中,一起努力共同进步!!
mui
hcoder 一直致力于奉献高质量的视频教程,官网上 mui、h5 等免费教程播放量已经达到10万+。
教程汇总
实战 : HUI APP实战教程 - 仿《京东优选》电商项目
知识点 : JavaScript 快速提高视频教程
实战: MUI、H5 APP 实战教程 - 仿《有道词典》
知识点 : HBuilder 8.0.1 APP开发 - 新功能全接触
知识点 : APP开发教程 - 启动动画
知识点 : APP开发实例教程 - 窗口切换
知识点 : 移动端图片剪裁、上传视频教程
知识点 : app开发教程-用户注册、登录
实战 : APP开发实战 - 新闻客户端
知识点 : HTML 5 开发教程
知识点 : mui 全套教程、 H5+ 沉浸式状态栏详解 、h5+ 地图api
mui
hcoder 一直致力于奉献高质量的视频教程,官网上 mui、h5 等免费教程播放量已经达到10万+。
教程汇总
实战 : HUI APP实战教程 - 仿《京东优选》电商项目
知识点 : JavaScript 快速提高视频教程
实战: MUI、H5 APP 实战教程 - 仿《有道词典》
知识点 : HBuilder 8.0.1 APP开发 - 新功能全接触
知识点 : APP开发教程 - 启动动画
知识点 : APP开发实例教程 - 窗口切换
知识点 : 移动端图片剪裁、上传视频教程
知识点 : app开发教程-用户注册、登录
实战 : APP开发实战 - 新闻客户端
知识点 : HTML 5 开发教程
知识点 : mui 全套教程、 H5+ 沉浸式状态栏详解 、h5+ 地图api
教程地址
http://www.hcoder.net/course/index/cate/4
pullRefresh 安卓无法滑动,iOS正常
正在写一个设备列表的下拉刷新页面,base的代码是从别的页面copy过来。加上下拉刷新后,下拉刷新正常使用,但是在Android手机上列表滑动时候感觉move事件被谁给吃了,列表滑动很是费力。iOS正常,经过与demo相比,发现一个大坑,给小伙伴们提个醒:
mui.init({
pullRefresh: {
container: '#pullrefresh',
down: {
contentdown: "下拉可以刷新",
contentover: "释放立即刷新",
contentrefresh: "正在TM刷新",
callback: refreshDeviceList
}
}
});
mui.plusReady(function() {
//注意:列表的自动滑动属性会影响滑动效果,必须注释掉
//mui('.mui-scroll-wrapper').scroll();
if(mui.os.android) {
setTimeout('refreshDeviceList()', 800);
} else {
refreshDeviceList();
}
});
注意mui('.mui-scroll-wrapper').scroll();这句话,会影响下拉刷新嵌套的列表的滑动效果,直接去掉,一切正常了。
正在写一个设备列表的下拉刷新页面,base的代码是从别的页面copy过来。加上下拉刷新后,下拉刷新正常使用,但是在Android手机上列表滑动时候感觉move事件被谁给吃了,列表滑动很是费力。iOS正常,经过与demo相比,发现一个大坑,给小伙伴们提个醒:
mui.init({
pullRefresh: {
container: '#pullrefresh',
down: {
contentdown: "下拉可以刷新",
contentover: "释放立即刷新",
contentrefresh: "正在TM刷新",
callback: refreshDeviceList
}
}
});
mui.plusReady(function() {
//注意:列表的自动滑动属性会影响滑动效果,必须注释掉
//mui('.mui-scroll-wrapper').scroll();
if(mui.os.android) {
setTimeout('refreshDeviceList()', 800);
} else {
refreshDeviceList();
}
});
注意mui('.mui-scroll-wrapper').scroll();这句话,会影响下拉刷新嵌套的列表的滑动效果,直接去掉,一切正常了。
收起阅读 »git 的 "Push to Upstream" 变灰无法使用的解决方法
使用HBuilder 在本地创建项目后,当分享到git云端时,往往会出现无法提交到远程服务的问题(应该是git插件的原因)。
解决方法:
到该项目的根目录中的 ".git" 文件夹中找到 "config" 文件,打开并添加以下代码,已有的代码不用重复覆盖,填上你的git地址。
[core]
repositoryformatversion = 0
filemode = false
logallrefupdates = true
[remote "origin"]
url = 你的git地址
fetch = +refs/heads/:refs/remotes/origin/
[branch "master"]
remote = origin
merge = refs/heads/master
rebase = false
如果依然不能提交到远程服务,可参考该文章:http://blog.csdn.net/chenshun123/article/details/46756087
使用HBuilder 在本地创建项目后,当分享到git云端时,往往会出现无法提交到远程服务的问题(应该是git插件的原因)。
解决方法:
到该项目的根目录中的 ".git" 文件夹中找到 "config" 文件,打开并添加以下代码,已有的代码不用重复覆盖,填上你的git地址。
[core]
repositoryformatversion = 0
filemode = false
logallrefupdates = true
[remote "origin"]
url = 你的git地址
fetch = +refs/heads/:refs/remotes/origin/
[branch "master"]
remote = origin
merge = refs/heads/master
rebase = false
如果依然不能提交到远程服务,可参考该文章:http://blog.csdn.net/chenshun123/article/details/46756087
收起阅读 »纯jsp实现微信支付,无需Java程序,完整绿色版复制即可用!
本代码优点:无需依赖java程序,两个jsp文件走天下,方便多个项目复制使用,完整绿色无污染!
吐槽一下腾讯,给的示例代码太复杂不好调试,直接给个简单能跑通的多好,先能跑通再加复杂逻辑才是王道!
1、先要有微信开放平台的账号,并创建应用,审核通过。并且获取微信支付能力。
2、创建应用在填写Android的签名的时候要去掉冒号,并且小写(备注: 签名是用的md5 )
3、微信支付,一定要打包为apk 格式的文件,并且需要用到自己的keystore证书
4、打包好的apk文件,安装在手机测试
废话不多说,上代码:
1、HBuilder端js代码,放个按钮调用doWxPay()方法即可:
var channels = null;
mui.plusReady(function() {
// 获取支付通道
plus.payment.getChannels(function(cs) {
channels = cs;
}, function(e) {
alert("获取支付通道失败:" + e.message);
});
});
var w=null;
function doWxPay() {
if (w) return;
w = plus.nativeUI.showWaiting();
//获取支付通道
var channel;
for(var i in channels) {
if(channels[i].id == "wxpay") {
channel = channels[i];
}
}
mui.ajax('http://www.mywebsitexxx.com/pay_wx.jsp', {
data: {
total: "1", //支付金额1分
body: "Test", //支付界面标题
out_trade_no: "123456789" //订单编号
},
type: 'post',
dataType: 'text',
timeout:20000,
success: function(data) {
w.close();
w = null;
data=data.replace(/\r\n/g,"").trim();
console.log(data);
plus.payment.request(channel, data, saveSuccess, saveFail);
},
error: function(xhr, errorType, error) {
w.close();
w = null;
alert(" error:"+error);
}
});
}
function saveSuccess(){
mui.toast("支付成功!");
}
function saveFail(error){
alert("支付失败!"+JSON.stringify(error));
}
2、服务端jsp代码pay_wx.jsp,放在网站根目录:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@page import="java.util.*"%>
<%@page import="java.io.*"%>
<%@page import="org.w3c.dom.*"%>
<%@page import="javax.xml.parsers.*"%>
<%@page import="javax.xml.transform.stream.*"%>
<%@page import="javax.xml.transform.*"%>
<%@page import="javax.xml.transform.dom.*"%>
<%@page import="java.security.MessageDigest"%>
<%@page import="org.apache.http.util.EntityUtils"%>
<%@page import="org.apache.http.client.HttpClient"%>
<%@page import="org.apache.http.*"%>
<%@page import="org.apache.http.entity.StringEntity"%>
<%@page import="org.apache.http.client.config.RequestConfig"%>
<%@page import="org.apache.http.client.methods.HttpPost"%>
<%@page import="org.apache.http.impl.client.HttpClientBuilder"%>
<%@page import="org.apache.http.conn.ssl.SSLConnectionSocketFactory"%>
<%@page import="org.apache.http.conn.socket.PlainConnectionSocketFactory"%>
<%@page import="org.apache.http.conn.socket.ConnectionSocketFactory"%>
<%@page import="org.apache.http.config.RegistryBuilder"%>
<%@page import="org.apache.http.impl.conn.BasicHttpClientConnectionManager"%>
<%!
public static String AppID="wxea521866668888";//
public static String MchID="13866668888";//商户id
public static String Key="UNaaaaabbbb87349866668888";//支付秘钥key
public String httpsPost(String url, String data) throws Exception {
BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build(),
null,
null,
null
);
HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connManager)
.build();
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(200000).setConnectTimeout(200000).build();
httpPost.setConfig(requestConfig);
StringEntity postEntity = new StringEntity(data, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(postEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity, "UTF-8");
}
public static String randomStr(int length) {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
public static String MD5(String data) throws Exception {
java.security.MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
public static String generateSignature(final Map<String, String> data, String key) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
sb.append("key=").append(key);
return MD5(sb.toString());
}
public static String mapToXml(Map<String, String> data) throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
org.w3c.dom.Document document = documentBuilder.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key: data.keySet()) {
String value = data.get(key);
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
try {
writer.close();
}
catch (Exception ex) {
}
return output;
}
public static Map<String, String> xmlToMap(String strXML) throws Exception {
try {
Map<String, String> data = new HashMap<String, String>();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
try {
stream.close();
} catch (Exception ex) {
}
return data;
} catch (Exception ex) {
throw ex;
}
}
%>
<%
HashMap<String, String> reqData = new HashMap<String, String>();
reqData.put("appid", AppID);
reqData.put("mch_id", MchID);
reqData.put("body", request.getParameter("body"));// 商品描述
reqData.put("out_trade_no", request.getParameter("out_trade_no")); // 商户订单号
reqData.put("total_fee", request.getParameter("total"));//支付金额
reqData.put("fee_type", "CNY");// 币种
reqData.put("spbill_create_ip", request.getRemoteAddr());
reqData.put("notify_url", "http://www.mywebsitexxx.com/webhook_wx.jsp");//微信回调notify页面
reqData.put("trade_type", "APP");
reqData.put("nonce_str",randomStr(20));
String sign = generateSignature(reqData, Key);
reqData.put("sign", sign);//打包签名
String reqBody = mapToXml(reqData);
String result = httpsPost("https://api.mch.weixin.qq.com/pay/unifiedorder", reqBody);
//System.out.println(result);
Map map = xmlToMap(result);
String prepay_id = (String) map.get("prepay_id");
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonce_str = randomStr(20);
String str = "appid=" + AppID + "&noncestr=" + nonce_str
+ "&package=Sign=WXPay" + "&partnerid=" + MchID
+ "&prepayid=" + prepay_id + "×tamp=" + timestamp
+ "&key=" + Key;
String newSign = MD5(str);
StringBuffer json = new StringBuffer();
json.append("{\"appid\":\"");
json.append(AppID);
json.append("\",\"noncestr\":\"");
json.append(nonce_str);
json.append("\",\"package\":\"");
json.append("Sign=WXPay");
json.append("\",\"partnerid\":\"");
json.append(MchID);
json.append("\",\"prepayid\":\"");
json.append(prepay_id);
json.append("\",\"timestamp\":");
json.append(timestamp);
json.append(",\"sign\":\"");
json.append(newSign);
json.append("\"}");
//System.out.println(json.toString());
out.print(json.toString());
%>
3、微信回调notify页面jsp代码webhook_wx.jsp,放在网站根目录:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@page import="java.net.HttpURLConnection"%>
<%@page import="java.net.URL"%>
<%@page import="java.util.*"%>
<%@page import="java.io.*"%>
<%@page import="org.w3c.dom.*"%>
<%@page import="javax.xml.parsers.*"%>
<%!
public static Map<String, String> xmlToMap(String strXML) throws Exception {
try {
Map<String, String> data = new HashMap<String, String>();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
try {
stream.close();
} catch (Exception ex) {
}
return data;
} catch (Exception ex) {
throw ex;
}
}
%>
<%
StringBuffer xmlStr = new StringBuffer();
String line = null;
try {
request.setCharacterEncoding("utf-8");
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
xmlStr.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("微信支付:"+xmlStr);
Map data = xmlToMap(xmlStr.toString());
if("SUCCESS".equals(data.get("return_code"))
&& "SUCCESS".equals(data.get("result_code"))){
Double totalFee = new Double(data.get("total_fee").toString())/100;
//TODO:这里加判断逻辑,编写更新订单状态的代码,或直接调用写好的Java类
System.out.println(totalFee );
out.println("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
} catch (Exception e) {
e.printStackTrace();
}
}else{
out.println("ERROR");
}
%>
完毕,打包apk即可测试。
注:各种依赖jar包还得自行去下载。
本代码优点:无需依赖java程序,两个jsp文件走天下,方便多个项目复制使用,完整绿色无污染!
吐槽一下腾讯,给的示例代码太复杂不好调试,直接给个简单能跑通的多好,先能跑通再加复杂逻辑才是王道!
1、先要有微信开放平台的账号,并创建应用,审核通过。并且获取微信支付能力。
2、创建应用在填写Android的签名的时候要去掉冒号,并且小写(备注: 签名是用的md5 )
3、微信支付,一定要打包为apk 格式的文件,并且需要用到自己的keystore证书
4、打包好的apk文件,安装在手机测试
废话不多说,上代码:
1、HBuilder端js代码,放个按钮调用doWxPay()方法即可:
var channels = null;
mui.plusReady(function() {
// 获取支付通道
plus.payment.getChannels(function(cs) {
channels = cs;
}, function(e) {
alert("获取支付通道失败:" + e.message);
});
});
var w=null;
function doWxPay() {
if (w) return;
w = plus.nativeUI.showWaiting();
//获取支付通道
var channel;
for(var i in channels) {
if(channels[i].id == "wxpay") {
channel = channels[i];
}
}
mui.ajax('http://www.mywebsitexxx.com/pay_wx.jsp', {
data: {
total: "1", //支付金额1分
body: "Test", //支付界面标题
out_trade_no: "123456789" //订单编号
},
type: 'post',
dataType: 'text',
timeout:20000,
success: function(data) {
w.close();
w = null;
data=data.replace(/\r\n/g,"").trim();
console.log(data);
plus.payment.request(channel, data, saveSuccess, saveFail);
},
error: function(xhr, errorType, error) {
w.close();
w = null;
alert(" error:"+error);
}
});
}
function saveSuccess(){
mui.toast("支付成功!");
}
function saveFail(error){
alert("支付失败!"+JSON.stringify(error));
}
2、服务端jsp代码pay_wx.jsp,放在网站根目录:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@page import="java.util.*"%>
<%@page import="java.io.*"%>
<%@page import="org.w3c.dom.*"%>
<%@page import="javax.xml.parsers.*"%>
<%@page import="javax.xml.transform.stream.*"%>
<%@page import="javax.xml.transform.*"%>
<%@page import="javax.xml.transform.dom.*"%>
<%@page import="java.security.MessageDigest"%>
<%@page import="org.apache.http.util.EntityUtils"%>
<%@page import="org.apache.http.client.HttpClient"%>
<%@page import="org.apache.http.*"%>
<%@page import="org.apache.http.entity.StringEntity"%>
<%@page import="org.apache.http.client.config.RequestConfig"%>
<%@page import="org.apache.http.client.methods.HttpPost"%>
<%@page import="org.apache.http.impl.client.HttpClientBuilder"%>
<%@page import="org.apache.http.conn.ssl.SSLConnectionSocketFactory"%>
<%@page import="org.apache.http.conn.socket.PlainConnectionSocketFactory"%>
<%@page import="org.apache.http.conn.socket.ConnectionSocketFactory"%>
<%@page import="org.apache.http.config.RegistryBuilder"%>
<%@page import="org.apache.http.impl.conn.BasicHttpClientConnectionManager"%>
<%!
public static String AppID="wxea521866668888";//
public static String MchID="13866668888";//商户id
public static String Key="UNaaaaabbbb87349866668888";//支付秘钥key
public String httpsPost(String url, String data) throws Exception {
BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager(
RegistryBuilder.<ConnectionSocketFactory>create()
.register("http", PlainConnectionSocketFactory.getSocketFactory())
.register("https", SSLConnectionSocketFactory.getSocketFactory())
.build(),
null,
null,
null
);
HttpClient httpClient = HttpClientBuilder.create()
.setConnectionManager(connManager)
.build();
HttpPost httpPost = new HttpPost(url);
RequestConfig requestConfig = RequestConfig.custom().setSocketTimeout(200000).setConnectTimeout(200000).build();
httpPost.setConfig(requestConfig);
StringEntity postEntity = new StringEntity(data, "UTF-8");
httpPost.addHeader("Content-Type", "text/xml");
httpPost.setEntity(postEntity);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
return EntityUtils.toString(httpEntity, "UTF-8");
}
public static String randomStr(int length) {
String base = "abcdefghijklmnopqrstuvwxyz0123456789";
Random random = new Random();
StringBuffer sb = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
public static String MD5(String data) throws Exception {
java.security.MessageDigest md = MessageDigest.getInstance("MD5");
byte[] array = md.digest(data.getBytes("UTF-8"));
StringBuilder sb = new StringBuilder();
for (byte item : array) {
sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
}
return sb.toString().toUpperCase();
}
public static String generateSignature(final Map<String, String> data, String key) throws Exception {
Set<String> keySet = data.keySet();
String[] keyArray = keySet.toArray(new String[keySet.size()]);
Arrays.sort(keyArray);
StringBuilder sb = new StringBuilder();
for (String k : keyArray) {
sb.append(k).append("=").append(data.get(k).trim()).append("&");
}
sb.append("key=").append(key);
return MD5(sb.toString());
}
public static String mapToXml(Map<String, String> data) throws Exception {
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder= documentBuilderFactory.newDocumentBuilder();
org.w3c.dom.Document document = documentBuilder.newDocument();
org.w3c.dom.Element root = document.createElement("xml");
document.appendChild(root);
for (String key: data.keySet()) {
String value = data.get(key);
if (value == null) {
value = "";
}
value = value.trim();
org.w3c.dom.Element filed = document.createElement(key);
filed.appendChild(document.createTextNode(value));
root.appendChild(filed);
}
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
DOMSource source = new DOMSource(document);
transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
StringWriter writer = new StringWriter();
StreamResult result = new StreamResult(writer);
transformer.transform(source, result);
String output = writer.getBuffer().toString(); //.replaceAll("\n|\r", "");
try {
writer.close();
}
catch (Exception ex) {
}
return output;
}
public static Map<String, String> xmlToMap(String strXML) throws Exception {
try {
Map<String, String> data = new HashMap<String, String>();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
try {
stream.close();
} catch (Exception ex) {
}
return data;
} catch (Exception ex) {
throw ex;
}
}
%>
<%
HashMap<String, String> reqData = new HashMap<String, String>();
reqData.put("appid", AppID);
reqData.put("mch_id", MchID);
reqData.put("body", request.getParameter("body"));// 商品描述
reqData.put("out_trade_no", request.getParameter("out_trade_no")); // 商户订单号
reqData.put("total_fee", request.getParameter("total"));//支付金额
reqData.put("fee_type", "CNY");// 币种
reqData.put("spbill_create_ip", request.getRemoteAddr());
reqData.put("notify_url", "http://www.mywebsitexxx.com/webhook_wx.jsp");//微信回调notify页面
reqData.put("trade_type", "APP");
reqData.put("nonce_str",randomStr(20));
String sign = generateSignature(reqData, Key);
reqData.put("sign", sign);//打包签名
String reqBody = mapToXml(reqData);
String result = httpsPost("https://api.mch.weixin.qq.com/pay/unifiedorder", reqBody);
//System.out.println(result);
Map map = xmlToMap(result);
String prepay_id = (String) map.get("prepay_id");
String timestamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonce_str = randomStr(20);
String str = "appid=" + AppID + "&noncestr=" + nonce_str
+ "&package=Sign=WXPay" + "&partnerid=" + MchID
+ "&prepayid=" + prepay_id + "×tamp=" + timestamp
+ "&key=" + Key;
String newSign = MD5(str);
StringBuffer json = new StringBuffer();
json.append("{\"appid\":\"");
json.append(AppID);
json.append("\",\"noncestr\":\"");
json.append(nonce_str);
json.append("\",\"package\":\"");
json.append("Sign=WXPay");
json.append("\",\"partnerid\":\"");
json.append(MchID);
json.append("\",\"prepayid\":\"");
json.append(prepay_id);
json.append("\",\"timestamp\":");
json.append(timestamp);
json.append(",\"sign\":\"");
json.append(newSign);
json.append("\"}");
//System.out.println(json.toString());
out.print(json.toString());
%>
3、微信回调notify页面jsp代码webhook_wx.jsp,放在网站根目录:
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
<%@page import="java.net.HttpURLConnection"%>
<%@page import="java.net.URL"%>
<%@page import="java.util.*"%>
<%@page import="java.io.*"%>
<%@page import="org.w3c.dom.*"%>
<%@page import="javax.xml.parsers.*"%>
<%!
public static Map<String, String> xmlToMap(String strXML) throws Exception {
try {
Map<String, String> data = new HashMap<String, String>();
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
InputStream stream = new ByteArrayInputStream(strXML.getBytes("UTF-8"));
org.w3c.dom.Document doc = documentBuilder.parse(stream);
doc.getDocumentElement().normalize();
NodeList nodeList = doc.getDocumentElement().getChildNodes();
for (int idx = 0; idx < nodeList.getLength(); ++idx) {
Node node = nodeList.item(idx);
if (node.getNodeType() == Node.ELEMENT_NODE) {
org.w3c.dom.Element element = (org.w3c.dom.Element) node;
data.put(element.getNodeName(), element.getTextContent());
}
}
try {
stream.close();
} catch (Exception ex) {
}
return data;
} catch (Exception ex) {
throw ex;
}
}
%>
<%
StringBuffer xmlStr = new StringBuffer();
String line = null;
try {
request.setCharacterEncoding("utf-8");
BufferedReader reader = request.getReader();
while ((line = reader.readLine()) != null) {
xmlStr.append(line);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("微信支付:"+xmlStr);
Map data = xmlToMap(xmlStr.toString());
if("SUCCESS".equals(data.get("return_code"))
&& "SUCCESS".equals(data.get("result_code"))){
Double totalFee = new Double(data.get("total_fee").toString())/100;
//TODO:这里加判断逻辑,编写更新订单状态的代码,或直接调用写好的Java类
System.out.println(totalFee );
out.println("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
} catch (Exception e) {
e.printStackTrace();
}
}else{
out.println("ERROR");
}
%>
完毕,打包apk即可测试。
注:各种依赖jar包还得自行去下载。
快捷键混乱,设置无效
添加/取消缩进的快捷键和tab 切换的快捷键混乱在一起了,来提交BUG还说积分不够。。。尼玛真纠结被浪费的时间。。。
添加/取消缩进的快捷键和tab 切换的快捷键混乱在一起了,来提交BUG还说积分不够。。。尼玛真纠结被浪费的时间。。。




