由于苹果审核机制变化,除了JSPatch等热修复的应用受到影响外,另个影响较大的就是非法集成第三方支付SDK(尤其支付宝)而审核被拒。但是由于你懂的的原因,不想走IAP(In App Pay),所以当然想到了支付宝 WAP 支付。完成 WAP 支付大概花了三天多时间,但是有大概一天时间是在等签约,所以为了让大家和自己有需要的话快速集成,特意做一个总结。涉及 iOS(OC)和JS(HTML5)以及PHP,下面进入正题。

吐槽支付宝开放平台

之前我一直觉得只有微信的开发平台网站比较容易搞混,(一个是微信开放平台,另个是微信公众平台),但是接触支付宝后,深深陷入各个跳转和新旧文档难以自拔(我记得之前没这么乱啊,我知道网站迭代更新向后兼容不易,但是能不能稍微克制一下??)

先扔出个WAP支付开发文档的链接出来,大家最好直接输入链接,搜索引擎慎用。(你能明白花了很长时间研究文档最后发现是老版本的痛苦吗)
WAP支付开发文档

开发步骤

准备工作

1、注册商家等都不说了,很简单
2、虽然之前已经签约过 APP 支付功能,但是做手机网站支付的话还得继续签约手机网站支付功能,注意 APPID 是不一样的。签约网址在这里签约申请,开始的时候我以为我们运营同事已经帮忙申请好,但是最后在调支付宝接口的时候老是报错ISV权限不足,经过检查才发现是没有签约手机网站支付,提交申请审核时间是一个工作日。所以大家记得提前申请。
3、签约成功后,由于支付宝使用 RSA 数据加密方式,非对称加密,所以在本机可以openssl生成应用私钥和应用公钥(统称密钥),应用私钥在自己的代码中加密数据的时候会用到,应用公钥配置到支付宝后台产生支付宝公钥进行数据解密。注意下图,配置手机网站支付的时候选择左边的平台开放密钥,然后找到对应的APPID产品进行公钥配置。我一开始失误配置成了下面的mapi网关产品密钥,导致报错验签失败。

WX20170322-200717.png

接下来修改 OC代码调用支付宝SDK支付换成打开HTML网页,在网页里面完成支付功能。

注意后面的queryString,由于支付网页需要UID,考虑到方便快捷,没有选择用 WebViewJSBridge 进行数据交互,而是直接拼在链接后面。

// 阿里 wap 支付
- (void)wapPay {ZKSafariViewController *vc = [ZKSafariViewController new];NSString *oriUrl = @"...";NSString *queryStr = [NSString stringWithFormat:@"?uid=%@&fee=%@", _loginUser.uid, _total_fee];NSString *urlStr = [oriUrl stringByAppendingString:queryStr];vc.url = urlStr;[_applicationContext.navigationController pushViewController:vc animated:YES];
}

编写HTML页面,提交数据到PHP后端。(前端代码)

代码如下:

<form name="alipayment" id="alipayment" action='...AliPay/CreateWapPay' method=post>
// ... 一些 input 标签,提交到服务器
</form>
<script type="text/javascript">function GetDateNow() {let totalFee = getQueryStringArgs().total_fee,uid = getQueryStringArgs().uid;// ...document.getElementById("uid").value = uid;document.getElementById("total_fee").value = totalFee;// ...}GetDateNow();document.forms['alipayment'].submit();
</script>

集成 支付宝 PHP SDK 详细步骤(后端代码)
下1、载PHP DEMO
2、将SDK拖入项目文件,配置config.php文件,如下

$config = array ('app_id' => "...",//商户私钥,您的原始格式RSA私钥'merchant_private_key' => "...",//异步通知地址'notify_url' => "http://工程公网访问地址/alipay.trade.wap.pay-PHP-UTF-8/notify_url.php",//同步跳转'return_url' => "http://mitsein.com/alipay.trade.wap.pay-PHP-UTF-8/return_url.php",//编码格式'charset' => "UTF-8",//签名方式'sign_type'=>"RSA",//支付宝网关'gatewayUrl' => "https://openapi.alipay.com/gateway.do",//支付宝公钥,查看地址:https://openhome.alipay.com/platform/keyManage.htm 对应APPID下的支付宝公钥。'alipay_public_key' => "...",
);

3、

组装系统参数$sysParams(app_id, return_url, nofify_url, sign_type等),获取业务参数$apiParams(放在biz_content字段中)并将其加密如下
$enCryptContent = encrypt($apiParams['biz_content'], $this->encryptKey);
$apiParams['biz_content'] = $enCryptContent;
……
将系统参数和业务参数组装在一起进行签名
……
$totalParams = array_merge($apiParams, $sysParams);
//待签名字符串
$preSignStr = $this->getSignContent($totalParams);
//签名
$totalParams["sign"] = $this->generateSign($totalParams, $this->signType);

4、然后到了关键的地方,利用total_params拼接表单字符串,方法如下

/*** 建立请求,以表单HTML形式构造(默认)* @param $para_temp 请求参数数组* @return 提交表单HTML文本*/protected function buildRequestForm($para_temp) {$sHtml = "<form id='alipaysubmit' name='alipaysubmit' action='".$this->gatewayUrl."?charset=".trim($this->postCharset)."' method='POST'>";while (list ($key, $val) = each ($para_temp)) {if (false === $this->checkEmpty($val)) {//$val = $this->characet($val, $this->postCharset);$val = str_replace("'","'",$val);//$val = str_replace("\"",""",$val);$sHtml.= "<input type='hidden' name='".$key."' value='".$val."'/>";}}//submit按钮控件请不要含有name属性$sHtml = $sHtml."<input type='submit' value='ok' style='display:none;''></form>";$sHtml = $sHtml."<script>document.forms['alipaysubmit'].submit();</script>";return $sHtml;}

5、执行第4步生成的表单html代码被类AlipayTradeService进行echo到前端页面上,包含JS自动提交脚本,所以就直接调起了支付宝支付。为了让大家更加明白,生成的h5代码形式如下:

<form id='alipaysubmit' name='alipaysubmit' action='https://openapi.alipay.com/gateway.do?charset=UTF-8' method='POST'><input type='hidden' name='biz_content' value='{"productCode":"QUICK_WAP_PAY","body":null,"subject":null,"out_trade_no":"1234","total_amount":"100","timeout_express":"1m"}'/><input type='hidden' name='app_id' value='2088711989778894'/><input type='hidden' name='version' value='1.0'/><input type='hidden' name='format' value='json'/><input type='hidden' name='sign_type' value='RSA'/><input type='hidden' name='method' value='alipay.trade.wap.pay'/><input type='hidden' name='timestamp' value='2017-03-20 17:16:15'/><input type='hidden' name='alipay_sdk' value='alipay-sdk-php-20161101'/><input type='hidden' name='notify_url' value='http://.../notify_url.php'/><input type='hidden' name='return_url' value='http://.../return_url'/><input type='hidden' name='charset' value='UTF-8'/><input type='hidden' name='sign' value='vgU9ROZeES3fa6CPo5onwY2auGN7N6naNI8Wo5l2U/K6LPk2stkv0Cor5Dn57Xo83GefOnoPg5A/7dNLbZjTXioPaocrPg3LteDB/EV3zYHXUPsab7dPztW+7guQDbLXI1RtaEuPm85hjO2Cur5EmP3P3sAE1XVGYJHHtLJoAbKzm/I='/><input type='submit' value='ok' style='display:none;''>
</form>
<script>document.forms['alipaysubmit'].submit();</script>"

当上面的H5代码被echo到前端页面,会自动submit表单信息。继续往下看

在 iOS 中实现代理进行跳转(iOS 移动端代码)

自动提交后,当手机有安装支付宝的时候,在webView中实现一个协议方法即可自动跳转到支付宝客户端。如果没有安装,进入支付宝的H5收银台进行支付。协议方法如下

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest: (NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{NSString* reqUrl = request.URL.absoluteString;if ([reqUrl hasPrefix:@"alipays://"] || [reqUrl hasPrefix:@"alipay://"]) {BOOL bSucc = [[UIApplication sharedApplication]openURL:request.URL];if (!bSucc) {// 未安装支付宝 进入网页支付}return NO;}return YES;
}

善后工作

当支付成功后,会自动跳转到return_url页面,这个页面简单展示一下支付成功信息即可。注意并不能作为交易成功的凭证。
支付成功后,除了会进入上面提到的return_url,支付宝还会异步通知notify_url,并传递详细的交易信息,支付宝会根据上面传入的异步通知地址notify_url通过POST请求的形式将支付结果作为参数通知到商户后台系统。在这个接口中实现验签和支付成功的业务逻辑代码。

上面提到的常用的支付宝网站罗列一下

新版开发文档入口 https://openhome.alipay.com/developmentDocument.htm
查看是否已经签约 https://app.alipay.com/market/productIndex.htm
开放平台密钥管理 https://openhome.alipay.com/platform/keyManage.htm
调用支付宝网关接口https://openapi.alipay.com/gateway.do https://doc.open.alipay.com/doc2/detail.htm?treeId=203&articleId=105463&docType=1

分享几个这个项目中比较好用的函数

1、创建订单号 很简单,月日时分秒 + 5位随机数

/*** Created by ZK on 17/3/22.*/
// 创建订单编号
function generateOrderID(){var formatTime = function (date) {var month = date.getMonth() + 1,day = date.getDate(),hour = date.getHours(),minute = date.getMinutes(),second = date.getSeconds();return [month, day,hour, minute, second].map(formatNumber).join('') ;};function formatNumber(n) {n = n.toString();return n[1] ? n : '0' + n;}var nowDate = new Date(),dateStr = formatTime(nowDate),randomNum = Math.random()*1000000000,oriStr = dateStr + randomNum,orderID = oriStr.substr(0,15);return orderID;
}

2、取得 QueryString 参数值

function getQueryStringArgs() {var qs = (location.search.length > 0 ? location.search.substring(1) : ''),args = {},items = qs.length ? qs.split('&') : [],item = null,name = null,value = null,i = 0,len = items.length;for (i = 0; i < len; i ++) {item = items[i].split('=');name = decodeURIComponent(item[0]);value = decodeURIComponent(item[1]);if (name.length) {args[name] = value;}}return args;
}

3、另外一个比较好用的在PHP代码中插入JS代码实现弹出debug信息,如果服务器不支持write info,这招很方便。

echo '<script type="text/javascript">alert("testMsg");</script>';
// 输出变量内容
$name = 'dev_zk';
echo '<script type="text/javascript">alert('.$name.');</script>';

多分享几个坑

1、JS 脚本中的代码最好别用ES6以上的版本,除非你用babel自动转换ES5。我就栽坑了,写的ES6脚本在 iOSVersion <=9.0 的系统中全部失效报错,但是在移动应用中测试 JS 的不方便你是知道的,找了好久才意识到这个问题。高估了WebKit对JS的版本支持更新速度。
2、ISV权限不足 — 没有签约对应功能。
3、验签失败 — 没有在对应APPID设置正确公钥。

作者:KavinZhou
链接:https://www.jianshu.com/p/aee17c44e0d1

记录支付宝手机网站(WAP)支付踩过的坑相关推荐

  1. 支付宝手机网站支付实战踩坑

    准备 需求 需求就是最简单的对接支付宝支付接口 方案心路历程 简单用http对接一下,不过想了一下觉得第三方提供的SDK总是不用,所以打算尝试一下 支付宝新版SDK,从文档到git再安装到使用,然后放 ...

  2. 支付--支付宝手机网站支付(WAP)

    介绍: 这是放在微信供公众号内的一个项目,支付模块设计到微信公众号支付和支付宝手机网站支付,这次把支付宝手机网站支付整理下来. 文档: 支付宝手机网站支付的开发文档: https://docs.ope ...

  3. 支付宝手机网站支付签约强开WAP支付,提示“系统综合评估签约条件不满足”或不满足国家法律法规或支付宝用户服务协议等的解决方案!支付宝H5支付开通方法详解

    一.如何开通支付宝手机网站支付 正常来说,按照官方的指引要求填写相关资料,即可开通支付宝手机网站支付.但是,更多的时候我们的申请都会碰到一些阻力,常见的阻力就是"系统综合评估签约条件不满足, ...

  4. 支付宝wap端支付php对接_PHP接入支付宝手机网站支付、移动支付接口

    前面已经说完了 PHP接入支付宝 即时到帐接口 回调接口也已经完成.这篇主要讲 手机网站支付 . 移动支付 接口的调用.调用方式与即时到帐 基本一样. 关于代码部分的详细解释,请 参看 PHP接入支付 ...

  5. php手机网站支付宝_PHP实现支付宝手机网站支付功能

    PHP实现支付宝手机网站支付功能的方法:首先开通支付宝商家中心里面的手机网站支付:然后进入开发者中心,获取到APPID:接着去文档中心下载"DEMO":最后将"demo& ...

  6. 支付宝手机网站支付出现系统繁忙,请稍后再试

    今日在做一个文件搞定支付宝系列时,其中在做支付宝手机网站兼容微信浏览器时,遇到了不少坑,这里详细记录一下. 1.验签出错 按照支付宝提供的demo(alipay_in_weixin_demo),里面只 ...

  7. 支付宝手机网站支付补全信息提示 系统综合评估签约条件不满足解决

    申请支付宝 手机网站支付 成功后需补全经营信息,但是补全提交时提示  "系统综合评估签约条件不满足解决",需要检查下自己的支付宝账号是否满足以下申请条件: 1.申请前必须拥有经过实 ...

  8. 4 支付宝手机网站支付demo讲解

    目录 1 引言 2 业务流程 3 用户下单 4 商户系统处理订单信息 5 支付宝向用户展示支付信息 6 用户付款 7 同步通知与异步通知 1 引言 前面三小节我们已经学过如何使用支付宝手机网站支付的功 ...

  9. 对接支付宝手机网站支付接口,alin10071

    最近项目要增加支付宝扫二维码实现h5支付的功能,我们采用了调用支付宝手机网站支付接口:alipay.trade.wap.pay 但是每次调起返回都是 无可用支付方式 测了一天才发现是因为我的支付宝余额 ...

最新文章

  1. Swift基础--调用第三方OC项目
  2. Xcode iOS9.3 配置包 iOS10.0 配置包 iOS10.2 配置包 could not find developer disk image
  3. ASP.NET MVC Framework 系列
  4. GPIO及中断API函数
  5. 【Python7】csv/excel/matplotlib,排序/树遍历,线/进程,文件/xml操作,百度人脸API,aiohttp/hal/restful/curl
  6. Android事件处理之多点触摸与手势识别
  7. Web UI 自动化测试环境搭建 (转载自51测试天地第三十九期上)
  8. 动态添加模板列及保持页面状态
  9. 软件设计师习题笔记-重点习题二
  10. 01-贝叶斯算法(介绍)
  11. 家用宽带搭建个人服务器(一)
  12. java 成神之路 (一)
  13. Gradle's dependency cache may be corrupt (this sometimes occurs after a network connection timeout.)
  14. linux iio 设备驱动,Linux设备驱动之IIO子系统——IIO框架数据读取,linuxiio
  15. pyspark steaming常规语句及操作
  16. 同步以太网-SyncE介绍
  17. 西安邮电大学python期末考试_python想过期末考试再怎么学?
  18. 企业wifi安全管家,贴身又暖心的wifi管理系统
  19. ROCBOSS开源免费微社区轻论坛类源码
  20. oracle客户端测试连接失败,教你解决win7系统配置Oracle客户端连接失败的设置步骤...

热门文章

  1. 机器学习-推荐系统-itemCF算法
  2. 亚洲销售女神徐鹤宁经典语录――太过精辟,不学必悔
  3. wordcloud-1.6.0-cp37-cp37m-win_amd64.whl is not a supported wheel on this platform.
  4. 职教云python程序设计答案_智慧职教云课堂APPPython程序设计考试期末考试答案
  5. 知乎与腾讯联手整顿平台:如何净化社区生态圈
  6. win11如何安装apk安卓应用?
  7. 20191210九年
  8. QT:控件精讲(六)显示组件DisplayWidgets
  9. HTML中 用CSS样式实现 文字两边添加水平线
  10. Python课堂练习