微信支付之企业付款_付款金额超出限制。低于最小金额1.00元或累计超过20000.00元-程序员宅基地

技术标签: php  

企业付款业务是基于微信支付商户平台的资金管理能力,为了协助商户方便地实现企业向个人付款,针对部分有开发能力的商户,提供通过API完成企业付款的功能。 比如目前的保险行业向客户退保、给付、理赔。

企业付款将使用商户的可用余额,需确保可用余额充足。查看可用余额、充值、提现请登录商户平台“资金管理”进行操作。https://pay.weixin.qq.com/ 
注意: 与商户微信支付收款资金并非同一账户,需要单独充值。企业付款需要证书。

说到代码实现,又不得不吐槽一下官方文档(https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.php?chapter=14_2)和SDK(下载:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip)了,基本跟没有差不多,全靠程序猿自己摸索然后进行代码实现。

主要步骤:
(1)构造post请求的数据

这个,需要哪些参数可以参照文档:https://pay.weixin.qq.com/wiki/doc/api/tools/mch_pay.PHP?chapter=14_2,我根据文档构造方法如下:

  1. /** 
  2.  * 企业支付 
  3.  * @param string $openid    用户openID 
  4.  * @param string $trade_no  单号 
  5.  * @param string $money     金额 
  6.  * @param string $desc      描述 
  7.  * @return string   XML 结构的字符串 
  8.  */  
  9. public function pay($openid,$trade_no,$money,$desc){  
  10.     $data = array(  
  11.         'mch_appid' => WxPayConfig::APPID,  
  12.         'mchid'     => WxPayConfig::MCHID,  
  13.         'nonce_str' => self::getNonceStr(),  
  14.         //'device_info' => '1000',  
  15.         'partner_trade_no' => $trade_no//商户订单号,需要唯一  
  16.         'openid'    => $openid,  
  17.         'check_name'=> 'NO_CHECK'//OPTION_CHECK不强制校验真实姓名, FORCE_CHECK:强制 NO_CHECK:  
  18.         //'re_user_name' => 'jorsh', //收款人用户姓名  
  19.         'amount'    => $money * 100, //付款金额单位为分  
  20.         'desc'      => $desc,  
  21.         'spbill_create_ip' => self::getip()  
  22.     );  
  23.       
  24.     //生成签名  
  25.     $data['sign'] = self::makeSign($data);  
  26.     //构造XML数据  
  27.     $xmldata = self::array2xml($data);  
  28.     $url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/promotion/transfers';  
  29.     //发送post请求  
  30.     $res = self::curl_post_ssl($url$xmldata);  
  31.     if(!$res){  
  32.         return array('status'=>1, 'msg'=>"Can't connect the server" );  
  33.     }  
  34.     // 这句file_put_contents是用来查看服务器返回的结果 测试完可以删除了  
  35.     file_put_contents(APP_ROOT.'/Api/wxpay/logs/log2.txt',$res,FILE_APPEND);  
  36.       
  37.     //付款结果分析  
  38.     $content = self::xml2array($res);  
  39.     if(strval($content['return_code']) == 'FAIL'){  
  40.         return array('status'=>1, 'msg'=>strval($content['return_msg']));  
  41.     }  
  42.     if(strval($content['result_code']) == 'FAIL'){  
  43.         return array('status'=>1, 'msg'=>strval($content['err_code']),':'.strval($content['err_code_des']));  
  44.     }  
  45.     $resdata = array(  
  46.         'return_code'      => strval($content['return_code']),  
  47.         'result_code'      => strval($content['result_code']),  
  48.         'nonce_str'        => strval($content['nonce_str']),  
  49.         'partner_trade_no' => strval($content['partner_trade_no']),  
  50.         'payment_no'       => strval($content['payment_no']),  
  51.         'payment_time'     => strval($content['payment_time']),  
  52.     );  
  53.     return $resdata;  
  54. }  

(2)发送数据请求请求的curl函数,可以去官方下载:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip。下载完毕将证书改成自己的证书路径就可以了。
  1. /** 
  2.  * 企业付款发起请求 
  3.  * 此函数来自:https://pay.weixin.qq.com/wiki/doc/api/download/cert.zip 
  4.  */  
  5. public function curl_post_ssl($url$xmldata$second=30,$aHeader=array()){  
  6.     $ch = curl_init();  
  7.     //超时时间  
  8.     curl_setopt($ch,CURLOPT_TIMEOUT,$second);  
  9.     curl_setopt($ch,CURLOPT_RETURNTRANSFER, 1);  
  10.     //这里设置代理,如果有的话  
  11.     //curl_setopt($ch,CURLOPT_PROXY, '10.206.30.98');  
  12.     //curl_setopt($ch,CURLOPT_PROXYPORT, 8080);  
  13.     curl_setopt($ch,CURLOPT_URL,$url);  
  14.     curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,false);  
  15.     curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,false);  
  16.       
  17.     //以下两种方式需选择一种  
  18.       
  19.     //第一种方法,cert 与 key 分别属于两个.pem文件  
  20.     //默认格式为PEM,可以注释  
  21.     curl_setopt($ch,CURLOPT_SSLCERTTYPE,'PEM');  
  22.     curl_setopt($ch,CURLOPT_SSLCERT,WxPayConfig::SSLCERT_PATH);  
  23.     //默认格式为PEM,可以注释  
  24.     curl_setopt($ch,CURLOPT_SSLKEYTYPE,'PEM');  
  25.     curl_setopt($ch,CURLOPT_SSLKEY,WxPayConfig::SSLKEY_PATH);  
  26.       
  27.     //第二种方式,两个文件合成一个.pem文件  
  28.     //curl_setopt($ch,CURLOPT_SSLCERT,getcwd().'/all.pem');  
  29.    
  30.     ifcount($aHeader) >= 1 ){  
  31.         curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);  
  32.     }  
  33.    
  34.     curl_setopt($ch,CURLOPT_POST, 1);  
  35.     curl_setopt($ch,CURLOPT_POSTFIELDS,$xmldata);  
  36.     $data = curl_exec($ch);  
  37.     if($data){  
  38.         curl_close($ch);  
  39.         return $data;  
  40.     }  
  41.     else {   
  42.         $error = curl_errno($ch);  
  43.         echo "call faild, errorCode:$error\n";   
  44.         curl_close($ch);  
  45.         return false;  
  46.     }  
  47. }  

我将完整的代码封装成了一个类,可以直接引入项目更改一下配置参数就可以使用的,源码下载: http://download.csdn.net/detail/sinat_35861727/9858508

调用就超级简单了,引入项目之后就直接调用:

  1. //测试支付  
  2. public function test(){  
  3.       
  4.     $openid = 'ovprvtzBZaWXnZUadwgexOLNc93M';  
  5.     $trade_no = date('YmdHis').mt_rand(1000,9999);  
  6.     $res = self::pay($openid,$trade_no,1,'提现');  
  7.     return $res;  
  8. }  
  1. //引入企业付款类  
  2. require_once APP_ROOT.'/Api/merchpay.class.php';  
  3. $merch = new \MerchPay();  
  4. $res =  $merch->test();    
  5. print_r($res);  
支付失败时返回的数据:
  1. <xml>  
  2. <return_code><![CDATA[SUCCESS]]></return_code>  
  3. <return_msg><![CDATA[支付失败]]></return_msg>  
  4. <mch_appid><![CDATA[wx09e38d3dcca919a4]]></mch_appid>  
  5. <mchid><![CDATA[1314969701]]></mchid>  
  6. <result_code><![CDATA[FAIL]]></result_code>  
  7. <err_code><![CDATA[AMOUNT_LIMIT]]></err_code>  
  8. <err_code_des><![CDATA[付款金额超出限制。低于最小金额1.00元或累计超过20000.00元。]]></err_code_des>  
  9. </xml>  
支付成功返回:
  1. <xml>  
  2. <return_code><![CDATA[SUCCESS]]></return_code>  
  3. <return_msg><![CDATA[]]></return_msg>  
  4. <nonce_str><![CDATA[kxm3zzlobtmb90rfodfejhug6qfosstl]]></nonce_str>  
  5. <result_code><![CDATA[SUCCESS]]></result_code>  
  6. <partner_trade_no><![CDATA[201706011750279780]]></partner_trade_no>  
  7. <payment_no><![CDATA[1000018301201706017928874552]]></payment_no>  
  8. <payment_time><![CDATA[2017-06-01 17:50:28]]></payment_time>  
  9. </xml>  
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_36663951/article/details/76167773

智能推荐

古典密码技术_了解古典密码的算法 了解古典密码的详细步骤 掌握古典密码的基本原理-程序员宅基地

文章浏览阅读7.4k次,点赞4次,收藏18次。古典密码技术古典密码是密码学中的其中一个类型,其大部分加密方式都是利用替换式密码或移项式密码,有时则是两者的混合。其于历史中经常使用,但在现代由于计算机的出现,使得古典密码解密已经不再困难,已经很少使用,大部分的已经不再使用了。古典密码技术根据其基本原理大体可以分为两类:替换密码技术和换位密码技术。替换密码技术替换密码技术是基于符号替换的密码技术。一般有单字符单表替换密码技术、单字符多表..._了解古典密码的算法 了解古典密码的详细步骤 掌握古典密码的基本原理

liunx中ls -la-程序员宅基地

文章浏览阅读1.4w次,点赞2次,收藏7次。ls 列出目录(文件夹)中的文件和子目录-l 长格式列出-a 显示所有文件,包括隐藏文件和目录(所有以“.”为开始的文件和目录为隐藏文件)所以ls -la 是列出当前目录中的所有文件和目录,包括隐藏文件和目录但不是查看文件里面的内容,查看文件的里的内容用的是more,less,cat等命令_ls -la

Java pta 面对对象(下)_定义一个车辆类(vehicle)和它的一个子类——客车类(bus),具体要求如下:(1)车辆类v-程序员宅基地

文章浏览阅读984次,点赞21次,收藏18次。Java pta 面对对象(下)7-1 定义一个车辆类和它的一个子类——客车类7-2 jmu-Java-03面向对象基础-04-形状-继承_定义一个车辆类(vehicle)和它的一个子类——客车类(bus),具体要求如下:(1)车辆类v

图像处理中常用的彩色模型_cmy-程序员宅基地

文章浏览阅读3.6w次,点赞10次,收藏68次。颜色模型就是描述用一组数值来描述颜色的数学模型。在彩色图像处理中,选择合适的彩色模型是很重要的。从应用的角度来看,彩色模型可分为两类:面向硬件设备的彩色模型面向视觉感知的彩色模型_cmy

计算机毕业设计 SSM+Vue健身房系统 健身会员管理系统 健身俱乐部管理系统 健身会所管理系统 健身预约教练管理系统Java Vue MySQL数据库 远程调试 代码讲解_ssm vue健身管理系统源码百度网盘-程序员宅基地

文章浏览阅读146次。计算机毕业设计 SSM+Vue健身房系统 健身会员管理系统 健身俱乐部管理系统 健身会所管理系统 健身预约教练管理系统_ssm vue健身管理系统源码百度网盘

LangChain - Chain-程序员宅基地

文章浏览阅读771次,点赞20次,收藏25次。1、概览为什么我们需要链?2、快速入门 (Get started) - Using `LLMChain`多个变量 使用字典输入在 `LLMChain` 中使用聊天模型:3、异步 API4、不同的调用方法`__call__`调用仅返回输出键值 return_only_outputs只有一个输出键 run只有一个输入键5、自定义chain6、调试链 (Debugging chains)7、从 LangChainHub 加载8、添加记忆(state)9、序列化将chain 保存到

随便推点

TailwindCSS为前端开发者带来了什么?_tailwindcss的优点-程序员宅基地

文章浏览阅读2.3k次。什么是Tailwind CSS?Tailwind CSS是一个功能类优先的CSS框架,它集成了flex、text-center这样的类,Tailwind CSS希望实现的是开发者无需离开HTML页面,即可快速创建出各种样式效果。Tailwind CSS相较于其他CSS框架有什么优势?优势1:Tailwind CSS类名具有较好的语义化传统的语义化类名是CSS难以维护的重要原因,也就是说起名很麻烦,但是Tailwind CSS的语义化类名可以很好的解决这个问题,例如:text-lg:表示一个_tailwindcss的优点

python 设置全局变量-程序员宅基地

文章浏览阅读8.2k次,点赞3次,收藏14次。python 设置全局变量,跨文件使用_python 设置全局变量

遍历磁盘_遍历所有移动硬盘-程序员宅基地

文章浏览阅读1.2k次。#include "stdafx.h"#include int main(){ TCHAR buf[MAX_PATH] = {}; int nDriveType; //1 获取磁盘盘符 GetLogicalDriveStrings(MAX_PATH, buf); TCHAR* pDrives = buf; while (_遍历所有移动硬盘

element-ui的隐藏组件el-scrollbar的使用(解决原生滚动条没有隐藏的问题 高宽设置)_el-scrollbar__wrap-程序员宅基地

文章浏览阅读1.3w次,点赞9次,收藏27次。element-ui的官网页面使用的这个滚动条,但是在官网文档中没有介绍这个组件。在vue+elementui搭建的前端项目中使用这个el-scrollbar组件。在项目中使用这个组件时由于各层的样式没有设置好,可能会显示出原生的滚动条,特此记录。搭建脚手架项目,安装element-ui插件按需引入需要的组件import Vue from 'vue'import { Scrollbar} from 'element-ui'Vue.use(Scrollbar)使用<_el-scrollbar__wrap

LabVIEW开发TDS1000 和TDS2000 系列泰克示波器_泰克示波器 labview-程序员宅基地

文章浏览阅读392次,点赞2次,收藏3次。泰克示波器是经常用到的工具,一般手动操作即可,但有时候也要集成到系统中,需要程控。这时候先要下载厂家提供的例子,了解LabVIEW的demo。示波器的功能挺多的,手册也是几百上千页,需要哪些功能,查找对应的部分就可以了。附件给出了LabVIEW的demo,需要的时候可以下载。手册可以到官网上下载,如果查不到,也可以联系厂家在线的技术,他们也会及时提供的。这是LabVIEW的一个功能介绍,更多的使用方法与开发案例,欢迎登录官网,了解更多信息。根据通讯协议的相关的说明,编写了适合项目的程序。_泰克示波器 labview

USB转2路RS422串口_ch347转接rs422-程序员宅基地

文章浏览阅读958次。默认建议使用厂商提供的VCP串口驱动程序。CH342DS1.PDF - 南京沁恒微电子股份有限公司CH342技术手册,USB转双串口芯片,支持最高3M波特率,串口信号支持1.8~5V,内置晶振。CH342芯片支持最高4Mbps串口波特率,如果对波特率有更高的需求,可以选择支持9Mbps的高速USB转接芯片CH347,使用单个CH342芯片即可实现USB一拖二串口转接产品,内置USB收发器和控制器、高速全双工串口控制器、以及每个UART内置独立的串口收发FIFO,可轻松满足各类串口波特率下的连续稳定通信。_ch347转接rs422