竹磬网-邵珠庆の日记 生命只有一次,你可以用它来做些更多伟大的事情–Make the world a little better and easier


98月/180

H5计算器实现

发布在 邵珠庆

<!DOCTYPE html>
<html>
<meta name="content-type" content="text/html; charset=UTF-8">
<head>
<title>Calculator</title>
<!--将按键内容以字符串形式存储在文字框中当按钮为“=”时,调用eval方法计算结果然后将结果输出文字框中-->
<script type="text/javascript">
var numresult;
var str;
function onclicknum(nums) {
str = document.getElementById("nummessege");
str.value = str.value + nums;
}
function onclickclear() {
str = document.getElementById("nummessege");
str.value = "";
}
function onclickresult() {
str = document.getElementById("nummessege");
numresult = eval(str.value);
str.value = numresult;
}
</script>
</head>
<body bgcolor="affff" >
<!--定义按键表格,每个按键对应一个事件触发-->
<table border="1" align="center" bgColor="#bbff77"
style="height: 350px; width: 270px">
<tr>
<td colspan="4">
<input type="text" id="nummessege"
style="height: 90px; width: 350px; font-size: 50px" />
</td>
</tr>
<tr>
<td>
<input type="button" value="1" id="1" onclick="onclicknum(1)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="2" id="2" onclick="onclicknum(2)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="3" id="3" onclick="onclicknum(3)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="+" id="add" onclick="onclicknum('+')"
style="height: 70px; width: 90px; font-size: 35px">
</td>
</tr>
<tr>
<td>
<input type="button" value="4" id="4" onclick="onclicknum(4)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="5" id="5" onclick="onclicknum(5)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="6" id="6" onclick="onclicknum(6)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="-" id="sub" onclick="onclicknum('-')"
style="height: 70px; width: 90px; font-size: 35px">
</td>
</tr>
<tr>
<td>
<input type="button" value="7" id="7" onclick="onclicknum(7)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="8" id="8" onclick="onclicknum(8)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="9" id="9" onclick="onclicknum(9)"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="*" id="mul" onclick="onclicknum('*')"
style="height: 70px; width: 90px; font-size: 35px">
</td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="0" id="0" onclick="onclicknum(0)"
style="height: 70px; width: 190px; font-size: 35px">
</td>
<td>
<input type="button" value="." id="point" onclick="onclicknum('.')"
style="height: 70px; width: 90px; font-size: 35px">
</td>
<td>
<input type="button" value="/" id="division"
onclick="onclicknum('/')"
style="height: 70px; width: 90px; font-size: 35px">
</td>
</tr>
<tr>
<td colspan="2">
<input type="button" value="Del" id="clear"
onclick="onclickclear()"
style="height: 70px; width: 190px; font-size: 35px" />
</td>
<td colspan="2">
<input type="button" value="=" id="result"
onclick="onclickresult()"
style="height: 70px; width: 190px; font-size: 35px" />
</td>
</tr>
</table>
</body>
</html>
205月/170

手机无须ROOT和修改hosts在本地测试安卓和H5应用

发布在 邵珠庆

开发手机APP和 H5 应用经常需要在本地和线上环境分开测试,一般想到的操作都是修改hosts,我也一直这么干的,但手机上修改hosts是需要 ROOT权限的,这样太过麻烦,还有变砖头的风险,而且有些手机根本不能ROOT的。

忙和了一下午,总算完全达到预期,有点收获,下面说说重点,主要是两个:

  1. 本地 DNS 服务
  2. 网络代理

做个本地的 DNS 服务,有点像DNS劫持的感觉,这个是一劳永逸的办法
首先,你需要一个Linux 虚拟机或一台服务器
我下面的配置使用的 Centos7.0 系统,不通版本可能有些差别的。

一、安装 DNSMasq

# 安装
yum install dnsmasq -y 
service dnsmasq start

# 编辑配置参数
vi /etc/dnsmasq.conf

# 查找 resolv-file 去掉注释符,添加文件路径
# 表示 dnsmasq 会从这个指定的文件中寻找上游dns服务器
resolv-file=/etc/resolv.conf

# 查找 no-hosts , 确保前面有 # 井号的(表示被注释掉的),否则 hosts 配置不起作用
# 监听的IP
listen-address=127.0.0.1,192.168.0.103
strict-order
addn-hosts=/etc/hosts
cache-size=32768

# 配置到网卡参数,centos7 和 6 的网卡名是不同的,用ifconfig 查看替换下
# centos 7 以前
vi /etc/sysconfig/network-scripts/ifcfg-eth0
# centos7 不一定相同
vi /etc/sysconfig/network-scripts/ifcfg-enp3s0

#  最多只能写3个,注意原配置中若存在则需要调整
DNS1=127.0.0.1
DNS2=192.168.0.103
DNS3=202.101.172.35
#DNS3=202.101.172.47

# 保存后, resolv.conf 文件内容会自动更新的
cat /etc/resolv.conf

# 查看DNS是否已添加进去

# 注册服务
chkconfig dnsmasq on

# 重启
/etc/init.d/dnsmasq restart

# centos7 下使用的命令
systemctl restart dnsmasq

# 检查是否安装成功
netstat -tunlp|grep 53
yum install bind-utils

# 测试是否启用 DNS 配置
dig m.ai9475.com

# 编辑 hosts 文件,配置本地 DNS 劫持域名 IP 的映射关系
vi /etc/hosts
192.168.0.105 m.ai9475.com


这样服务端的 DNS 劫持就基本配置好了
下一步还需要在手机上设置 DNS 对应的 IP,

打开 网络设置 -> wifi连接 -> 修改网络 -> 高级 -> 静态IP方式 -> 修改第一个NSIP即可,第二个可用正常的公网DNS

如下图:

Android手机DNS配置

最后注意:修改 hosts 之后,需要重启 dnsmasq 还有 network 最好也重启

二、使用本地网络代理

这个方法比较有局限性,对 H5 网页应用还可以,对部分原生 APP 可能无效哦,但有个好处是配合一些软件可以做前端的抓包查看,对测试接口之类的查看数据很有用

我用到过两个软件,
1. Fiddler
这个软件使用很方便,网上有很多介绍,这里就不说了,但据说仅支持 windows 平台
2. Whistle
这个是开源的项目,跨平台,我目前用的是这个,配置也很简单
下面简单说下如何安装使用

依赖 Nodejs,所以先安装 nodejs
我这里图方便,就用 yum 的方式安装了

curl --silent --location https://rpm.nodesource.com/setup_4.x | bash -
yum install -y nodejs

下载速度可能有些忙,10KB/s 下载了好半天才下完,耐心等吧

npm install cnpm -g --registry=https://registry.npm.taobao.org
cnpm install -g whistle
w2 start

这样就完成了。。。

查看代理请求数据,就是抓包数据

http://127.0.0.1:8900
http://127.0.0.1:8899

:8899 是代理的端口,但也可以查看抓包数据

两个端口都可以看,下图看看效果先(图片可以直接拖拽查看大图)

手机无须ROOT不用修改hosts即可在本地测试安卓、苹果APP和H5应用

其他的就直接看官方说明文档吧,中文的,很清晰明了
https://avwo.github.io/whistle/install.html

后面就是手机上操作和上面的 DNS 设置是同一个地方

打开 网络设置 -> wifi连接 -> 修改网络 -> 高级 -> 代理(手动配置) -> 填写局域网中服务器的IP,如192.168.0.103,端口 8899 

如下图:

Android手机设置代理

最后就是修改服务器上的 hosts,参考上方 DNS 配置 hosts 的操作是一样的

差不多就这样设置好了。

最后需要注意的就是清除手机上的缓存,一定要关闭浏览器和应用,清理内存后再打开,否则手机上的 DNS 和网络设置可能没有切换过来的。

以上配置我都是在 Android 设备上测试的, iOS 没有应用可测试,不过按理说应该是一样的效果的。
虽然代理的方法对有些APP 不一定有用,但建议还是 DNS 和 代理一起上吧。。。就这样了。

1512月/160

微信支付开发 国内服务商接入H5支付

发布在 邵珠庆

服务商模式,适用于有软件开发能力的公司帮助其他商户接入微信支付。

  目前官方的政策是达到一定条件可以获取返佣,并且微信支付刚刚公布了星火计划,拿出资金帮助服务商做运营,同时微信支付也在和滴滴进行跨界的合作。
  1. 服务商在商户平台的特约商户管理里,可以帮助商户提交公司或者个体户的资料,申请通过后可以获得特约商户号和商户平台密码。
  2. 服务商可以在开发配置里配置默认关注的服务号appid,这个默认关注是使用服务商接口发生微信支付时的默认功能。
     目前刷卡支付没有金额门槛就可以默认关注,其他支付方式需要金额大于5元(具体推荐关注的规则,请看之前的一篇文章)。
  3. 设置默认关注时提示主体不一致,无法设置?
     微信规定这里默认关注服务号的公司主体和申请这个特约商户的主体是一样的,不然会报这个错。
     遇到这个错误找对接的商务经理解决, 需要签署额外的推荐关注的协议。
  4. 如果特约商户没有服务号,这里默认关注可以不设置,那么支付成功后没有默认关注。
  5. 服务商模式支持刷卡支付,公众号支付,扫码支付模式二(模式一不支持),APP支付(请咨询商户经理,额外开通权限)。
  6. 特约商户的开发配置里,有一个特约商户appid配置的按钮(接口里的sub_appid)是否需要绑定呢?
     首先要明确,这里添加sub_appid的作用,是为了微信支付返回sub_openid(用户在sub_appid下的openid)
     6.1 通常情况下不需要绑定特约商户appid
     6.2 一些特殊情况下,需要绑定特约商户appid
  以下分别说明这2点。
  7 针对6.1中提到的没有绑定特约商户appid,接口参数如何传?
     a . 特约商户没有服务号(appid)或者商户不需要知道用户在特约商户服务号(sub_appid)下的openid,那么appid是可以不绑定的
     b. 对于没有绑定特约商户appid,刷卡支付和扫码支付接口传如下参数:
        mchid 服务商商户号
        appid 服务商的appid
        sub_mch_id 特约商户的商户号
        key: 服务商的密钥
        证书: 服务商的证书
     c. 对于没有绑定特约商户appid,公众号支付的统一下单接口传如下参数:
        mchid 服务商商户号
        appid 服务商的appid
        openid 用户在服务商appid下的openid(授权获取用户信息接口)
        sub_mch_id 特约商户的商户号
        key: 服务商的密钥
        证书: 服务商的证书
  8. 针对6.2中提到的绑定特约商户appid,哪些情况下需要绑定appid?接口如何传?
     a. 哪些情况下需要绑定appid?
        一定需要获取用户在特约商户服务号(sub_appid)下的openid。
        常见的情况有2种:
        一是商户需要用这个openid和自己的CRM打通,
        二是很多商户都用一个服务号运营,为了方便运营需要拿到用户在这个服务号下的openid
     b. 绑定的时候遇到提示主体不一致?
        服务商在绑定的时候,也是需要绑定的服务号appid和特约商户的主体一致的,如果不一致会提示主体不一致的错误。
        遇到这个错误找对接的商务经理解决, 需要签署额外的联合运营函
     c. 有些极端的情况,一个特约商户号,绑定多个appid(可能商户希望运营到不同的服务号,这种情况也是允许的,不过比较少见,不建议这么做)
     d. 对于绑定了特约商户appid,刷卡支付和扫码支付接口传如下参数:
        mchid 服务商商户号
        appid 服务商的appid
        sub_appid 特约商户的appid
        sub_mch_id 特约商户的商户号
        key: 服务商的密钥
        证书: 服务商的证书
        此时,提交刷卡支付的微信回复里,会返回sub_openid (商户在特约商户sub_appid下的openid)
     e. 对于绑定了特约商户appid,公众号接口传如下参数:
        mchid 服务商商户号
        appid 服务商的appid
        sub_appid 特约商户的appid
        sub_openid 用户在特约商户sub_appid下的openid(授权获取用户信息接口)
        sub_mch_id 特约商户的商户号
        key: 服务商的密钥
        证书: 服务商的证书
  9. 服务商在商户平台申请开通的特约商户,这些特约商户本身是没有普通微信支付权限的服务商本身自己也是没有普通微信支付权限的
  10. 结算和退款
     结算: 资金默认结算到特约商户的对公账户
     退款: API接口退款权限和商户平台页面退款权限都默认在子商户身上。
     如果需要服务商用接口发起退款的权限,请联系商务经理,需要签署额外的协议.
  11. 服务商模式发红包
     服务商模式发红包是指,钱在子商户的微信账户上,而受理商代发红包
     目前这个功能也需要向商务经理申请,请咨询各自对接的商务经理
  12. 注意事项
      (0)demo里设置的参数全部都要填服务商的,而不是子商户的。
      (1)第一个区别是openid,demo里直接传的openid,服务商模式需要传sub_openid,获取的方式就不说明了,总之获取所需都是子商户即特约商户的appid,appsecret。
      (2)需要在传入页面多传一个sub_mch_id参数。
      (3)将调用的类中判断openid那里的代码注释掉,不然永远进不到下一步。
      (4)在服务商的微信支付商户后台设置授权目录,而不是像普通商户那样在公众平台后台来设置。

   13. 问题:使用商户支付,签名错误:
   按照微信的错误提示,在签名算法里面把参数和算的签名打印出来
   然后在微信的调试接口里与打印出来的参数,https://pay.weixin.qq.com/wiki/tools/signverify/
   核对发现最后的生成的签名其实是一致,当时就觉得微信的返回提示好坑
   后来又是各种尝试,appid、key各种参数的核对,证书位置,Linux文件目录权限之类的,发现都没有解决问题。
   最后在微信商户平台,重置了一下密钥就可以了

   14. 商户错误信息:
   [return_msg] => 普通商户不允许传sub_mch_id
   [return_msg] => 不识别的参数sub_mchid
   [return_msg] => 商户号mch_id与appid不匹配
   [return_msg] => 签名错误