WeChat redpack SDK
调用请求说明
- 请求 URL:
https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack
- 是否需要证书:是
- 请求方式: POST
请求参数(必填)
字段名 | 字段 | 示例值 | 类型 | 说明 |
---|---|---|---|---|
随机字符串 | nonce_str | 5K8264ILTKCH16CQ2502SI8ZNMTM67VS | String(32) | 随机字符串,不长于 32 位 |
商户号 | mch_billno | 1234567890 | String(32) | 微信支付的商户号 |
公众账号 appid | wxappid | wx1234567890abcdef | String(32) | 微信公众号的 appid (在mp.weixin.qq.com 申请的) |
商户名称 | send_name | 京东商城 | String(32) | 红包发送者名称 |
商户订单号 | mch_billno | 1234567890201606011234567890 | String(28) | 每个订单号必须唯一,组成:mch_id+yyyymmdd+10位一天内不能够重复的数字。 |
用户 openid | re_openid | oxTWIuGaIt6gTKsQRLau2M0yL16E | String(32) | 接受红包的用户在 wxappid 下的 openid |
Ip 地址 | client_ip | 192.168.0.1 | String(15) | 调用接口的机器的 IP 地址 |
付款金额 | total_amount | 1000 | int | 红包金额,单位是分。红包金额范围:¥1 ~ ¥200 |
红包发放总人数 | total_num | 1 | int | 红包发放总人数 |
红包祝福语 | wishing | 恭喜发财 | String(128) | 红包祝福语 |
活动名称 | act_name | 拜年 | String(32) | 活动名称 |
备注 | remark | 备注 | String(256) | 备注信息 |
签名 | sign | 5K8264ILTKCH16CQ2502SI8ZNMTM67VS | String(32) | 生成的签名 |
数据示例:
1 | <xml> |
实现步奏
获取随机字符串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15/**
* 获取指定长度的随机字符串
* ASCII 码: a-z: 97-122; A-Z: 65-90
* @param int $length
* @return string
*/
public function getRandom($length = 32) {
$nonce_str = '';
for ($i=0; $i<$length; $i++) {
$random = rand(0, 61);
$c = $random < 10 ? rand(0, 9) : chr(rand(1, 26) + rand(0, 1)*32 + 64);
$nonce_str .= $c;
}
return $nonce_str;
}整合请求发送的数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25/**
* 微信发送红包的请求数据(除了签名参数 sign)
* @return array
*/
public function angPaoData() {
// 活动名称
$act_name = 'act_name';
// 备注
$remark = 'remark';
$data = array(
'nonce_str' => getRandom(32),
'mch_billno' => $mch_billno.date('YmdHis').rand(1000, 9999),
'mch_id' => $mch_billno, // 商户号
'wxappid' => $wxappid, // 公众号 appid
'send_name' => $send_name, // 商户名称
're_openid' => $open_id, // 用户 openid
'total_amount' => $total_amount, // 红包金额
'total_num' => 1, // 红包发放人数
'wishing' => $wishing, // 红包祝福语
'client_ip' => $client_ip, // 当前客户端 IP 地址
'act_name' => $act_name,
'remark' => $remark,
);
return $data;
}签名算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19function getSign($data) {
global $_W;
ksort($data, SORT_STRING);
$stringA = '';
// 第一步,将所有发送的参数按照 key=value 的格式组成字符串 stringA,
// 并且 key 要按照 ASCII 码从小到大排序(字典序)
foreach ($data as $k => $v) {
if ($k && $v && $k != 'sign') {
$stringA .= "{$k}={$v}&";
}
}
// 第二步,在 stringA 最后拼接上 key 得到 stringSignTemp 字符串,
// 并对 stringSignTemp 进行 MD5 运算,再将得到的字符串所有字符转换为大写
// key 设置路径:微信商户平台(pay.weixin.qq.com)-->账户设置-->API安全-->密钥设置
$setting = uni_setting($_W['uniacid'], array('payment'));
$key = $setting['payment']['wechat']['apikey'];
$stringSignTemp = $stringA . "key=" . $key;
return strtoupper(md5($stringSignTemp));
}发送数据的时候,不要忘记了将数据转换成指定的 xml 格式
1
2
3
4
5
6
7
8
9
10
11
12
13/**
* 将数据转换成符合传送要求的 xml 格式
* @param $data
* @return string
*/
function array2xml($data) {
$xml = "<xml>";
foreach ($data as $k => $v) {
$xml .= "<" . $k . "><![CDATA[" . $v . "]]></" .$k . ">";
}
$xml .= "</xml>";
return $xml;
}获取微信支付证书文件
为了安全,一般将证书的内容保存到数据库中,使用的时候读取出来,保存到文件中去,用完之后,及时删除掉。
1 | /** |
用 CURL 发送数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37/**
* @param $url
* @param $vars
* @param int $second
* @param array $aHeader
* @return bool|mixed
*/
function curl_post_ssl($vars, $second=30, $aHeader=array())
{
$url = 'https://api.mch.weixin.qq.com/mmpaymkttransfers/sendredpack';
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_TIMEOUT, $second);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
//cert 与 key 分别属于两个.pem文件
//请确保您的libcurl版本是否支持双向认证,版本高于7.20.1
foreach ($this->getPayFile() as $k => $v) {
curl_setopt($ch, constant($k), $v);
}
if( count($aHeader) >= 1 ){
curl_setopt($ch, CURLOPT_HTTPHEADER, $aHeader);
}
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $vars);
$data = curl_exec($ch);
if($data){
curl_close($ch);
return $data;
}
else {
$error = curl_errno($ch);
//echo "call faild, errorCode:$error\n";
curl_close($ch);
return false;
}
}发送红包
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17/**
* 发送红包
* @return bool|mixed
*/
public function angPaoPay() {
// 红包请求数据
$data = $this->angPaoData();
$data['sign'] = $this->getSign($data);
// 将数据转换成 xml 格式
$postXml = array2xml($data);
$responseXml = $this->curl_post_ssl($postXml);
// 为了证书安全,及时删掉
foreach ($this->getPayFile() as $file) {
unlink($file);
}
return $responseXml;
}