apicloud、weixinpay官方提供了两种方案。

本模块封装了两套支付方案:

方案一:开发者通过 getOrderId、payOrder 自己处理签名过程(微信开放平台建议把 getOrderId 放在服务器端执行);

方案二:通过 config 接口和 pay 接口把签名过程交予模块内部处理。config 接口的参数可通过 key.xml 文件配置。
  (本支付方案用于开发阶段测试验证账号的正确性,正式发版时请使用支付方案一)

方案二、属于本地测试账号是否完整的流程,正式使用的话使用方案一。

方案一、微信支付流程为:

、获取与支付订单。(这个订单号是微信生成的)。
、调用微信支付。

完整的方案一支付流程为:

1、申请微信开发平台的账号、创建移动应用、申请开发者资质认证(整个过程APICLOUD官方网站已经给出了相当明确的操作步骤,与实际操作没有差异,按照文档一步一步来,是没有问题的),附带链接地址:http://docs.apicloud.com/Others/Open-SDK-Integration-Guide/weChat

2、配置移动应用中 config.xml 文件

  <feature name="wxPay">
<param name="urlScheme" value="wxd0d84bbf23b4a0e4"/>
<param name="apiKey" value="wxd0d84bbf23b4a0e4"/>
<param name="apiSecret" value="a354f72aa1b4c2b8eaad137ac81434cd"/>
</feature>

3、getOrderId(),将获取预支付订单号,建议将获取预支付订单号放置服务器端执行。(服务端代码如下:)

$dataArr = array(
'appid' => $appId,
'mch_id' => $mchId,
'nonce_str' => getNonceStr(),
'body' => $body,
'attach' => $attach,
'out_trade_no' => getNonceStr(),
'total_fee' => $totalFee,
'spbill_create_ip' => $cIp,
'notify_url' => $url,
'trade_type' => 'APP'
); //转XML格式
function createXML($rootNode, $arr) {
//创建一个文档,文档时xml的,版本号为1.0,编码格式utf-8
$xmlObj = new DOMDocument('1.0', 'UTF-8');
//创建根节点
$Node = $xmlObj - > createElement($rootNode);
//把创建好的节点加到文档中
$root = $xmlObj - > appendChild($Node);
//开始把数组中的数据加入文档
foreach($arr as $key => $value) {
//如果是$value是一个数组
if (is_array($value)) {
//先创建一个节点
$childNode = $xmlObj - > createElement($key);
//将节点添加到$root中
$root - > appendChild($childNode);
//循环添加数据
foreach($value as $key2 => $val2) {
//创建节点的同时添加数据
$childNode2 = $xmlObj - > createElement($key2, $val2);
//将节点添加到$childNode
$childNode - > appendChild($childNode2);
}
} else {
//创建一个节点,根据键和值
$childNode = $xmlObj - > createElement($key, $value);
//把节点加到根节点
$root - > appendChild($childNode);
}
}
//把创建好的xml保存到本地
$xmlObj - > save('xml/log.xml');
$str = $xmlObj - > saveXML();
// echo $str;
//返回xml字符串
return $str;
} //封装签名算法
function MakeSign($arr) {
//签名步骤一:按字典序排序参数
ksort($arr);
$string = ToUrlParams($arr);
//签名步骤二:在string后加入KEY
$string = $string.
"&key=".$key;
//签名步骤三:MD5加密
$string = md5($string);
//签名步骤四:所有字符转为大写
$result = strtoupper($string);
return $result;
} /**
* 格式化参数格式化成url参数
*/
function ToUrlParams($arr) {
$buff = "";
foreach($arr as $k => $v) {
if ($k != "sign" && $v != "" && !is_array($v)) {
$buff. = $k.
"=".$v.
"&";
}
}
$buff = trim($buff, "&");
return $buff;
} //随机字符串(不长于32位)
function getNonceStr($length = ) {
$chars = "abcdefghijklmnopqrstuvwxyz0123456789";
$str = "";
for ($i = ; $i < $length; $i++) {
$str. = substr($chars, mt_rand(, strlen($chars) - ), );
}
return $str;
} function curl($url, $post_data) {
$headerArray = array(
'Accept:application/json, text/javascript, */*',
'Content-Type:application/x-www-form-urlencoded',
'Referer:https://mp.weixin.qq.com/'
); $ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
// 对认证证书来源的检查,0表示阻止对证书的合法性的检查。
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
// 从证书中检查SSL加密算法是否存在
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, ); //关闭直接输出
curl_setopt($ch, CURLOPT_POST, ); //使用post提交数据
curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); //设置 post提交的数据
curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.69 Safari/537.36'); //设置用户代理
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray); //设置头信息 $loginData = curl_exec($ch); //这里会返回token,需要处理一下。 return $loginData; $token = array_pop($token);
curl_close($ch);
} /**
* 解析xml文档,转化为对象
* @param String $xmlStr xml文档
* @return Object 返回Obj对象
*/
function xmlToObject($xmlStr) {
if (!is_string($xmlStr) || empty($xmlStr)) {
return false;
}
// 由于解析xml的时候,即使被解析的变量为空,依然不会报错,会返回一个空的对象,所以,我们这里做了处理,当被解析的变量不是字符串,或者该变量为空,
  直接返回false
libxml_disable_entity_loader(true);
$postObj = json_decode(json_encode(simplexml_load_string($xmlStr, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
//将xml数据转换成对象返回
return $postObj;
}
//=====================执行=======================
$sign = MakeSign($dataArr);//签名生成
$dataArr['sign'] = $sign; $xmlStr = createXML('xml', $dataArr);//统一下单xml数据生成
$reArr = explode('?>', $xmlStr);
$reArr = end($reArr); $xml = curl('https://api.mch.weixin.qq.com/pay/unifiedorder', $reArr);//发送请求 统一下单数据 //解析返回的xml字符串
$re = xmlToObject($xml); //判断统一下单是否成功
if ($re['result_code'] == 'SUCCESS') { //支付请求数据
$payData = array(
'appid' => $re['appid'],
'partnerid' => $re['mch_id'],
'prepayid' => $re['prepay_id'],
'noncestr' => getNonceStr(),
'package' => 'Sign=WXPay',
'timestamp' => time()
); //生成支付请求的签名
$paySign = MakeSign($payData); $payData['sign'] = $paySign; //拼接成APICLOUD所需要支付数据请求
$payDatas = array(
'apiKey' => $re['appid'],
'orderId' => $re['prepay_id'],
'mchId' => $re['mch_id'],
'nonceStr' => $payData['noncestr'],
'package' => 'Sign=WXPay',
'timeStamp' => $payData['timestamp'],
'sign' => $paySign
); //返回支付请求数据
echo json_encode($payDatas);
} else {
$re['payData'] = "error";
echo json_encode($re);
}

4、预支付下单成功后,将拼接好的支付请求数据返回,也就是上述代码中数组$payDatas(注意:第二次参与签名的字段是:appid、partnerid、prepayid、noncestr、package、timestamp),app端代码如下:

api.ajax({
url: baseUrl +'/api/v1/mallOrder/toPay?memberId=' +memberId+ '&orderId=' +orderId,
timeout: ,
dataType: 'json',
method: 'get'
}, function(ret, err) {
api.hideProgress();
/*** 登录异常 ***/
if (err) {
api.toast({
      msg:'网络异常,请稍后重试',
      duration: '',
      localtion: 'middle'
     });
return;
}
var wxPay = api.require('wxPay');
var data = ret.data;
wxPay.payOrder(data, function(ret, err) {
var statue = false;
if (ret.status) {
statue = true;
openPayResult(statue);
} else {
statue = false;
openPayResult(statue);
}
}); });

5、以上描述,已经亲测没有问题,如果代码或叙述有问题的,欢迎各位大神指教批评;如果有帮到各位初学者的不胜荣幸;另外说下我之前遇到过支付过程中返回-1的问题:这个问题不得不说APICLOUD官网有那么一点点的坑,官网上面payOrder()的参数为:appKey、orderId、mchId、nonceStr、timeStamp、package,就会以为参与第二次支付签名的参数是这些,但其实并不是,那么参与第二次支付签名的参数是:appid、partnerid、prepayid、noncestr、package、timestamp,生成签名后,需要将payOrder()所需要的参数一一对应重新填写(appKey==appid、orderId==prepayid、mchId==partnerid、nonceStr==noncestr、package==package、timeStamp==timestamp)。

移动APP 微信支付完整过程(wxPay 方案一)的更多相关文章

  1. 微信公众号支付|微信H5支付|微信扫码支付|小程序支付|APP微信支付解决方案总结

    最近负责的一些项目开发,都用到了微信支付(微信公众号支付.微信H5支付.微信扫码支付.APP微信支付).在开发的过程中,在调试支付的过程中,或多或少都遇到了一些问题,今天总结下,分享,留存. 先说注意 ...

  2. ThinkPHP5.0 实现 app微信支付功能

    相对于之前随笔写的<ThinkPHP5.0实现app支付宝支付功能>来说,php对接app微信支付功能就相对简单的多了,最近有加我的朋友问到app微信支付,所以我把app微信支付的demo ...

  3. app微信支付

    <?php namespace app\api\controller\v1; use think\Request; use app\api\exception\weappay\lib\WxPay ...

  4. APP微信支付报错《商户号该产品权限未开通,请前往商户平台>产品中心检查后重试》

    问题 最近项目使用MUI,HBuilder.开发打包H5的app 在开发H5 plus支付的时候,遇到以下问题: App微信支付调官方的统一下单接口返回错误信息 {return_msg=商户号该产品权 ...

  5. thinkPHP实现APP微信支付

    控制器 class Pay extends Controller { const WX_PAY_URL = "https://api.mch.weixin.qq.com/pay/unifie ...

  6. app微信支付-java服务端接口 支付-查询-退款

    个人不怎么看得懂微信的文档,看了很多前辈的写法,终于调通了,在这里做一下记录. 首先来定义各种处理类(微信支付不需要特殊jar包,很多处理需要自己封装,当然也可以自己写完打个jar包) 参数要用jdo ...

  7. APP微信支付Java后台的实现(springmvc)

    第一次做微信支付,阅读完开发文档后,下了个官方demo,摸索了好久,期间也出现了好多问题,终于是实现生成预支付订单以及支付成功后接收微信服务器通知,不多说了,直接上代码: 一.工具类 Constant ...

  8. java中微信统一下单采坑(app微信支付)

    app支付前java后台统一下单文档:https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1 微信支付接口签名校验工具:https ...

  9. APIcloud制作APP 微信支付与支付宝支付

    首先要在云端绑定相应模块如alipay和wxpay其次编写代码. 配置区域 var cfg = { webName:'',//APP名字 payDebug:true, isUseWxPay:true, ...

随机推荐

  1. [cogs396] [网络流24题#4] 魔术球 [网络流,最大流,最小路径覆盖]

    本题枚举每多一个球需要多少个柱子,可以边加边边计算,每次只需要判断$i-Dinic()$即可:特别注意边界. #include <iostream> #include <algori ...

  2. 用循环链表实现Josephus问题

    Josephus问题:设有n个人围坐在一个圆桌周围,现从第s个人开始报数,数到第m的人出列,然后从出列的下一个人重新开始报数,数到第m的人又出列.如此反复直到所有的人全部出列为止. 思路:构建一个没有 ...

  3. gap lock/next-key lock浅析Basic-Paxos协议日志同步应用

    http://www.cnblogs.com/renolei/p/4673842.html 当InnoDB在判断行锁是否冲突的时候, 除了最基本的IS/IX/S/X锁的冲突判断意外, InnoDB还将 ...

  4. Android測试环境变量配置表

    要改动的文件是~/bash_profile这个配置文件,内容例如以下: # Setting PATH for Java JAVA_HOME="/Library/Java/JavaVirtua ...

  5. 优秀软件project师必备的7大特性

    不是每个程序猿都能成为优秀的软件project师. 在过去的6年时间里,我在Ooyala.Quora和now Quip这3个创业公司面试过许很多多挺有发展潜力的"种子选手".他们都 ...

  6. Top10Servlet

    <span style="font-size:18px;">/** * Top10 * author:杨鑫 */ package servlet; import jav ...

  7. Raphaeljs入门到精通(二)

    这节我们将介绍Raphaeljs中元素的属性和事件,案例还是以上一篇的代码展开 <!DOCTYPE html> <html xmlns="http://www.w3.org ...

  8. js原生offsetParent解析

    offsetParent是个仅仅读属性,返回近期显示指定位置的容器元素的引用. 假设元素没有指定位置,近期的元素或者根元素(标准模式下是html,怪异模式下是body)就是offsetParent. ...

  9. iOS学习(3)

    4. 这个写法会出什么问题: @property (copy) NSMutableArray *array; 两个问题:1.加入,删除,改动数组内的元素的时候,程序会由于找不到相应的方法而崩溃.由于 ...

  10. VIM 移动

    基础 字符移动 k 上移 k h 左移 h l l 右移 j j 下移 你也可以使用键盘上的方向键来移动,但这么做h j k l的存在就失去了意义 之所以使用h j k l来控制方向,其主要目的是让你 ...