前言:微信支付现在分为v2版和v3版,2014年9月10号之前申请的为v2版,之后申请的为v3版。V3版的微信支付没有paySignKey参数.

php 微信支付类

<?php

class Wechat {

    protected $wechat_config;

    //https://pay.weixin.qq.com/wiki/doc/api/app/app.php?chapter=9_1
public function __construct($wechat_config = [])
{
if(empty($wechat_config)){
$wechat_config = [
'appid'=>'',
'mch_id'=>'',
'api_key'=>'',
'appsecret'=>'',
'notify_url'=>'',
];
}
$this->wechat_config = $wechat_config; } //生成预支付订单
public function wx_pay($body,$total_fee,$out_trade_no,$attach = 'charge_order') {
$nonce_str = $this->rand_code(); //调用随机字符串生成方法获取随机字符串
$data['appid'] = $this->wechat_config['appid']; //appid
$data['mch_id'] = $this->wechat_config['mch_id'] ; //商户号
$data['body'] = $body;
$data['spbill_create_ip'] = $this->get_client_ip(); //ip地址
$data['total_fee'] = $total_fee; //金额
$data['out_trade_no'] = $out_trade_no; //商户订单号,不能重复
$data['nonce_str'] = $nonce_str; //随机字符串
$data['notify_url'] = $this->wechat_config['notify_url']; //回调地址,用户接收支付后的通知,必须为能直接访问的网址,不能跟参数
$data['trade_type'] = 'APP'; //支付方式
$data['attach'] = $attach; //商户携带订单的自定义数据
//将参与签名的数据保存到数组 注意:以上几个参数是追加到$data中的,$data中应该同时包含开发文档中要求必填的剔除sign以外的所有数据 $data['sign'] = self::getSign($data,$this->wechat_config['api_key']); //获取签名 $xml = self::ToXml($data); //数组转xml
//curl 传递给微信方
$url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
//header("Content-type:text/xml");
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL, $url);
if(stripos($url,"https://")!==FALSE){
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
} else {
curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,TRUE);
curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,2);//严格校验
}
//设置header
curl_setopt($ch, CURLOPT_SSLVERSION, CURL_SSLVERSION_TLSv1);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
//要求结果为字符串且输出到屏幕上
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
//设置超时
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
curl_setopt($ch, CURLOPT_POST, TRUE);
//传输文件
curl_setopt($ch, CURLOPT_POSTFIELDS, $xml);
//运行curl
$data = curl_exec($ch);
//返回结果
if($data){ curl_close($ch);
//返回成功,将xml数据转换为数组.
$re = self::FromXml($data); if($re['return_code'] != 'SUCCESS'){
return [
'code'=>'201',
'msg'=>$re['return_msg']
];
}
else{
//接收微信返回的数据,传给APP!
$arr =array(
'prepayid' =>$re['prepay_id'],
'appid' => $this->wechat_config['appid'],
'partnerid' => $this->wechat_config['mch_id'],
'package' => 'Sign=WXPay',
'noncestr' => $nonce_str,
'timestamp' =>strval(time()),
);
//第二次生成签名
$sign = self::getSign($arr,$this->wechat_config['api_key']);
$arr['sign'] = $sign;
$arr['code'] = '200';
$arr['msg'] = '签名成功';
return $arr;
}
} else {
$error = curl_errno($ch);
curl_close($ch);
return [
'code'=>'201',
'msg'=>"curl出错,错误码:$error"
]; }
} //参数要组装成xml格式
public static function ToXml($data = array()){
if (!is_array($data) || count($data) <= 0) {
return '数组异常';
} $xml = "<xml>";
foreach ($data as $key => $val) {
if (is_numeric($val)) {
$xml .= "<" . $key . ">" . $val . "</" . $key . ">";
} else {
$xml .= "<" . $key . "><![CDATA[" . $val . "]]></" . $key . ">";
}
}
$xml .= "</xml>";
return $xml;
} public static function FromXml($xml)
{
if(!$xml){
echo "xml数据异常!";
}
//将XML转为array
//禁止引用外部xml实体
libxml_disable_entity_loader(true);
$data = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
return $data;
} //生成随机字符串
private function rand_code(){
$str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';//62个字符
$str = str_shuffle($str);
$str = substr($str,0,32);
return $str;
} /*
获取当前服务器的IP
*/
private function get_client_ip(){
if ($_SERVER['REMOTE_ADDR']) {
$cip = $_SERVER['REMOTE_ADDR'];
} elseif (getenv("REMOTE_ADDR")) {
$cip = getenv("REMOTE_ADDR");
} elseif (getenv("HTTP_CLIENT_IP")) {
$cip = getenv("HTTP_CLIENT_IP");
} else {
$cip = "unknown";
}
return $cip;
} //生成签名
public static function getSign($params,$api_key) {
ksort($params); //将参数数组按照参数名ASCII码从小到大排序
foreach ($params as $key => $item) {
if (!empty($item)) { //剔除参数值为空的参数
$newArr[] = $key.'='.$item; // 整合新的参数数组
}
} $stringA = implode("&", $newArr); //使用 & 符号连接参数
$stringSignTemp = $stringA."&key=".$api_key; //拼接key
// key是在商户平台API安全里自己设置的
$stringSignTemp = MD5($stringSignTemp); //将字符串进行MD5加密
$sign = strtoupper($stringSignTemp); //将所有字符转换为大写
return $sign;
} }

调起微信支付

        //生成微信支付预订单信息
$wechat_config = [
'appid'=>$this->config->openWeixin->appid,
'mch_id'=>$this->config->openWeixin->mch_id,
'api_key'=>$this->config->openWeixin->api_key,
'appsecret'=>$this->config->openWeixin->appsecret,
'notify_url'=>$this->config->openWeixin->notify_url,
];
$order_no = date('YmdHis').rand(1000,9999);
$money = 1;
$wechat = new Wechat($wechat_config);
$wechat_data = $wechat->wx_pay('test',$money,$order_no,'aid_order'); if($wechat_data['code'] != 200){
echo $wechat_data['msg'];die;
}
$result = [ 'order_no'=>$order_no , 'money'=>$money, 'wechat_data'=>$wechat_data, ];
print_r($result);die;

微信支付回调

 // 微信支付回调
public function wx_notifyAction(){
defined('BASE_PATH') || define('BASE_PATH', getenv('BASE_PATH') ?: realpath(dirname(__FILE__) . '/../..'));
//接收微信返回的数据数据,返回的xml格式
$xmlData = file_get_contents('php://input');
//将xml格式转换为数组
$data = Wechat::FromXml($xmlData);
//用日志记录检查数据是否接受成功,验证成功一次之后,可删除。
$file_name = BASE_PATH.'/log'.date('Ymd').'.txt';
//$file = fopen($file_name, 'a+') or die("Unable to open file!");;
//fwrite($file,'test:'.json_encode($data));die;
//为了防止假数据,验证签名是否和返回的一样。
//记录一下,返回回来的签名,生成签名的时候,必须剔除sign字段。
$sign = $data['sign'];
unset($data['sign']);
if($sign == Wechat::getSign($data,$this->config->openWeixin->api_key)){
//签名验证成功后,判断返回微信返回的
if ($data['result_code'] == 'SUCCESS') {
//根据返回的订单号做业务逻辑
$res = false;
if($data['attach'] == 'aid_order'){
$model = new PetAidOrder();
//宠物援助
$PetAidOrderData = $model::findFirst([
'order_no = :out_trade_no: AND pay_type = 2 AND status = 2',
'bind'=>[
'out_trade_no'=>$data['out_trade_no'],
]
]);
$getPetAidData = PetAid::findFirst([
'id = :pet_aid_id:',
'bind'=>[
'pet_aid_id'=>$PetAidOrderData->pet_aid_id
]
]);
if($PetAidOrderData && $getPetAidData){
/*===================事务开启================================*/
$connection = $model->getWriteConnection();
$connection->begin();
//更新订单数据
$PetAidOrderData->status = 1;
$PetAidOrderData->pay_time = time();
//更新项目数据
$getPetAidData->get_money += $PetAidOrderData->money;
if($PetAidOrderData->update() && $a = $getPetAidData->update()){$connection->commit();
$res = true;
} } }elseif($data['attach'] == 'rescue_order'){
$model = new UserRescueOrder();
//爱心捐献
$UserRescueOrderData = $model::findFirst([
'order_no = :out_trade_no: AND pay_type = 2 AND status = 2',
'bind'=>[
'out_trade_no'=>$data['out_trade_no'],
]
]); $getUserRescueAuthData = UserRescueAuth::findFirst([
'id = :user_resuce_auth_id:',
'bind'=>[
'user_resuce_auth_id'=>$UserRescueOrderData->user_resuce_auth_id
]
]); if($UserRescueOrderData && $getUserRescueAuthData){
/*===================事务开启================================*/
$connection = $model->getWriteConnection();
$connection->begin();
//更新订单数据
$UserRescueOrderData->status = 1;
$UserRescueOrderData->pay_time = time();
//更新救助中心数据
$getUserRescueAuthData->donation_money += $UserRescueOrderData->money; if($UserRescueOrderData->update() && $getUserRescueAuthData->update()){
$connection->commit();
$res = true;
}
} } //处理完成之后,告诉微信成功结果!
if($res == true){
echo '<xml>
<return_code><![CDATA[SUCCESS]]></return_code>
<return_msg><![CDATA[OK]]></return_msg>
</xml>';
exit();
}else{
$file = fopen($file_name, 'a+');
fwrite($file,date("Y-m-d H:i:s")."错误信息:数据修改失败,".json_encode($data).PHP_EOL);
}
}
//支付失败,输出错误信息
else{
$file = fopen($file_name, 'a+');
fwrite($file,date("Y-m-d H:i:s")."错误信息:支付失败,".json_encode($data).PHP_EOL);
}
}
else{
$file = fopen($file_name, 'a+');
fwrite($file,date("Y-m-d H:i:s")."错误信息:签名验证失败,".json_encode($data).PHP_EOL);
} }

  

php 微信支付V3 APP支付的更多相关文章

  1. asp.net core 微信扫码支付(扫码支付,H5支付,公众号支付,app支付)之1

    2018-08-13更新生成二维码的方法 在做微信支付前,首先要了解你需要什么方式的微信支付,目前本人做过的支付包含扫码支付.H5支付.公众号支付.App支付等,本人使用的是asp.net mvc c ...

  2. 微信支付(APP支付)-服务端开发(一)

    微信支付,首先需要注册一个商户平台公众账号,(网址:https://pay.weixin.qq.com/index.php/home/d_login) 目前微信支付的接入方式有四种方式:公众号支付,A ...

  3. 微信、支付宝App支付-JPay0.0.2发布

    JPay 对微信App支付.支付宝App支付的二次封装,对外提供一个相对简单的接口以及支付结果的回调 GitHub:https://github.com/Javen205/JPay OsChina:h ...

  4. 微信支付之App支付

    项目接入微信支付的准备工作: 注册成为开发者,进行资质认证,这里是需要300元的审核费用的: 在微信商户平台创建应用,提交等待审核(大致需要5-7个工作日): 应用审核通过之后,进入应用,开通微信支付 ...

  5. asp.net core 微信APP支付(扫码支付,H5支付,公众号支付,app支付)之4

    微信app支付需要以下参数,类封装如下 public class WxPayModel { /// <summary> /// 应用ID /// </summary> publ ...

  6. uni-app - 支付(app支付、小程序支付、h5(微信端)支付)

    App支付.小程序支付.h5(微信端)支付 APP支付(内置) appPay.js /** * 5+App支付,仅支持支付宝以及微信支付 * * 支付宝Sdk集成,微信sdk未集成 * * @para ...

  7. 微信JSAPI 公众号支付 H5支付以及APP支付 WEBAPI接口开发测试

    统一下单入口 调用该方法入口: public void WxPayAPI() { //string PayPrice ="99.9"; ////订单号 //string Payor ...

  8. ThinkPHP 5 整合支付宝微信支付(支付宝H5,微信H5、APP支付、公众号支付)

    因项目没有PC站所以没有写电脑网站支付. Pay.php支付控制器 <?php // +----------------------------------------------------- ...

  9. php支付走过的坑(微信篇 包含h5支付和app支付 注册 秘钥 环境等等配置)

    支付这东西,说容易也容易,说难也难 代码这玩意还比较好说 但是 如果没有demo 直接去看官方文档 十有八九一脸懵逼 今天就整理一下 支付这块走过的坑 涉及 微信h5支付 支付宝h5支付 (api文档 ...

随机推荐

  1. Day1 Python基础学习——概述、基本数据类型、流程控制

    一.Python基础学习 一.编程语言分类 1.简介 机器语言:站在计算机的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件 汇编语言:站在计算机的角度,简写的英文标识符取代二进制去编 ...

  2. Linux下安装zookeeper集群(奇数个)

    1.  解压zookeeper压缩包 2.  data里创建“myid”文件(命令touch myid),内容是1(命令 echo 1 >> myid) 3.  zoo.cnf里配置dat ...

  3. NgDL:【第二周】NN基础

    1.计算图的导数计算 正向比如说是计算代价函数值,反向就是增大多少a/b/c对J的影响,也就是导数的意义,这里讲的是求导链式法则. 2.向量化 节约大量计算时间 简直是100倍的时间,看来之前实现的那 ...

  4. WireShark过滤器选项

    首先说几个最常用的关键字,"eq" 和 "=="等同,可以使用 "and" 表示并且,"or"表示或者."!& ...

  5. [Java in NetBeans] Lesson 14. ArrayList and Collections

    这个课程的参考视频和图片来自youtube. 主要学到的知识点有: 1. Collection: container that contians objects. 2. Difference betw ...

  6. 最新版 INSPINIA IN+ - WebApp Admin Theme v2.7.1,包含asp.net MVC5示例代码,做管理系统最佳的选择。

    下载地址:http://download.csdn.net/download/wulang1988/10039402 最新版 INSPINIA IN+ - WebApp Admin Theme v2. ...

  7. 如何快速知道一个颜色的rgb值

    1.如果你想使用某种颜色缺不知道rgb值是多少,可以将一张图片用系统自带的画图(我的系统是win7)0工具打开,点击编辑颜色就会出现调色板,然后就可以选择查看具体颜色的rgb值了 2.如果你想知道某个 ...

  8. Ubuntu中使用pip3报错

    使用pip3 出现以下错误: Traceback (most recent call last): File “/usr/bin/pip3”, line 9, in from pip import m ...

  9. Service Fabric下删除实例并注销应用

    Service Fabric下删除实例并注销应用: 以应用名称:Application1为例 1.打开PowerShell 2.连接集群: Connect-ServiceFabricCluster - ...

  10. JS实例4

    根据当前年的前五年后五年的年月日 <select id="nian" onclick="Bian()"></select>年 <s ...