Wallogit.com
2017 © Pedro Peláez
微信公众号开发php封装
微信公众平台php版开发包 * 支持消息加解密方式的明文模式、兼容模式、安全模式 * 支持自动接入微信公众平台(步骤), (*1)
Wechat (处理自动接入、获取与回复微信消息)(使用说明) * 接收普通消息/事件推送 * 被动回复(文本、图片、语音、视频、音乐、图文) * 转发到多客服接口, (*2)
Api (处理需要access_token的主动接口)(使用说明) * 主送发送客服消息(文本、图片、语音、视频、音乐、图文) * 多客服功能(客服管理、多客服回话控制、获取客服聊天记录等) * 素材管理(临时素材、永久素材、素材统计) * 自定义菜单管理(创建、查询、删除菜单) * 微信JSSDK(生成微信JSSDK所需的配置信息) * 账号管理(生成带参数的二维码、长链接转短链接接口) * 用户管理(用户分组管理、设置用户备注名、获取用户基本信息、获取用户列表、网页授权获取用户基本信息) * 微信公众号支付(JSAPI) * 微信App支付(App) * 数据统计接口(开发中...), (*3)
项目内 demo/demo_simple.php, (*4)
require 'wechat-php-sdk/autoload.php';
use Yunfeit\WechatPhpSdk\Wechat;
$wechat = new Wechat(array(
'appId' => 'wx733d7f24bd29224a',
'token' => 'Yunfeit',
'encodingAESKey' => '072vHYArTp33eFwznlSvTRvuyOTe5YME1vxSoyZbzaV'
));
// 获取消息
$msg = $wechat->serve();
// 回复消息
if ($msg->MsgType == 'text' && $msg->Content == '你好') {
$wechat->reply("你也好!");
} else {
$wechat->reply("听不懂!");
}
手动引入, (*5)
<?php require "wechat-php-sdk/autoload.php"; // 引入自动加载SDK类的方法 use Yunfeit\WechatPhpSdk\Wechat; use Yunfeit\WechatPhpSdk\Api; ...
使用 composer, (*6)
#安装composer依赖 composer require "Yunfeit/wechat-php-sdk:1.*" composer dump-autoload --optimize
require "vendor/autoload.php"; use Yunfeit\WechatPhpSdk\Wechat; use Yunfeit\WechatPhpSdk\Api;
ThinkPHP 内使用, (*7)
将SDK内 src 文件夹重命名为 Yunfeit, 拷贝至 ThinkPHP/Library/ 下即可使用 Wechat 和 Api 类库., (*8)
Thinkphp控制器内使用SDK的DEMO:, (*9)
具体代码见: 项目内 demo/demo_thinkPHP.php, (*10)
$wechat = new \Yunfeit\WechatPhpSdk\Wechat(array(
'appId' => $appId,
'token' => $token,
'encodingAESKey' => $encodingAESKey
));
$api = new \Yunfeit\WechatPhpSdk\Api(
array(
'appId' => $appId,
'appSecret' => $appSecret,
'get_access_token' => function(){
// 用户需要自己实现access_token的返回
...
},
'save_access_token' => function($token) {
// 用户需要自己实现access_token的保存
...
}
)
);
官方wiki, (*11)
以项目中的 demo/demo_simple.php 为例, (*12)
开发者中心, 进入修改服务器配置页面URL填写demo_simple.php的访问地址, 比如http://wx.diary8.com/demo/demo_simple.php,确保外网可访问到Token和EncodingAESKey, 消息加解密方式可任意选择demo.php里配置项appId和token, appId为AppID(应用ID),token为第3部填写的token, 如果消息加解密方式选择了兼容模式或安全模式,还需要填写encodingAESKey
服务器配置表单$wechat = new Wechat(array(
// 开发者中心-配置项-AppID(应用ID)
'appId' => 'wx733d7f24bd29224a',
// 开发者中心-配置项-服务器配置-Token(令牌)
'token' => 'Yunfeit',
// 开发者中心-配置项-服务器配置-EncodingAESKey(消息加解密密钥)
// 可选: 消息加解密方式勾选 兼容模式 或 安全模式 需填写
'encodingAESKey' => '072vHYArTp33eFwznlSvTRvuyOTe5YME1vxSoyZbzaV'
));
// 获取微信消息
$msg = $wechat->serve();
// 回复微信消息
if ($msg->MsgType == 'text' && $msg->Content == '你好') {
$wechat->reply("你也好!");
} else {
$wechat->reply("听不懂!");
}
接受到的普通消息与事件推送会原样以数组对象返回,具体每种消息结构请看:, (*13)
官方wiki 接收普通消息 官方wiki 接收事件推送, (*14)
$msg = $wechat->serve();
官方wiki, (*15)
$wechat->reply('hello world!');
// 或者
$wechat->reply(array(
'type' => 'text',
'content' => '嘿嘿,呵呵~~'
));
$wechat->reply(array(
'type' => 'image',
// 通过素材管理接口上传多媒体文件,得到的id
'media_id' => 'Uq7OczuEGEyUu--dYjg7seTm-EJTa0Zj7UDP9zUGNkVpjcEHhl7tU2Mv8mFRiLKC'
));
$wechat->reply(array(
'type' => 'voice',
// 通过素材管理接口上传多媒体文件,得到的id
'media_id' => 'rVT43tfDwjh4p1BV2gJ5D7Zl2BswChO5L_llmlphLaTPytcGcguBAEJ1qK4cg4r_'
));
$wechat->reply(array(
'type' => 'video',
// 通过素材管理接口上传多媒体文件,得到的id
'media_id' => 'yV0l71NL0wtpRA8OMX0-dBRQsMVyt3fspPUzurIS3psi6eWOrb_WlEeO39jasoZ8',
'title' => '视频消息的标题', //可选
'description' => '视频消息的描述' //可选
));
$wechat->reply(array(
'type' => 'music',
'title' => '音乐标题', //可选
'description' => '音乐描述', //可选
'music_url' => 'http://me.diary8.com/data/music/2.mp3', //可选
'hqmusic_url' => 'http://me.diary8.com/data/music/2.mp3', //可选
'thumb_media_id' => 'O39wW0ZsXCb5VhFoCgibQs5PupFb6VZ2jH5A8gHUJCJz2Qmkrb7objoTue7bGTGQ',
));
$wechat->reply(array(
'type' => 'news',
'articles' => array(
array(
'title' => '图文消息标题1', //可选
'description' => '图文消息描述1', //可选
'picurl' => 'http://me.diary8.com/data/img/demo1.jpg', //可选
'url' => 'http://www.example.com/' //可选
),
array(
'title' => '图文消息标题2',
'description' => '图文消息描述2',
'picurl' => 'http://me.diary8.com/data/img/demo2.jpg',
'url' => 'http://www.example.com/'
),
array(
'title' => '图文消息标题3',
'description' => '图文消息描述3',
'picurl' => 'http://me.diary8.com/data/img/demo3.jpg',
'url' => 'http://www.example.com/'
)
)
));
$wechat->reply(array(
'type' => 'transfer_customer_service',
'kf_account' => 'test1@test' // 可选
));
由于微信的access_token请求次数有限制,, (*16)
用户需要自己实现access_token的获取和保存,, (*17)
否则access_token每次都会被更新,请求限额很快就用完了., (*18)
$api = new Api(
array(
'appId' => $appId,
'appSecret' => $appSecret,
'get_access_token' => function() {
// 用户需要在这里实现access_token的返回
...
},
'save_access_token' => function($token) {
// 用户需要在这里实现access_token的保存
...
}
)
);
access_token可以保存在数据库、Memcached、xcache 等., (*19)
当同一个微信号被用于多个项目中,access_token需要全局维护., (*20)
以下DEMO使用了Memcached缓存access_token, (*21)
具体代码见: demo/demo_message.php, (*22)
use Yunfeit\WechatPhpSdk\Wechat;
use Yunfeit\WechatPhpSdk\Api;
// AppID(应用ID)
$appId = 'wx733d7f24bd29224a';
// AppSecret(应用密钥)
$appSecret = 'c6de6zcw78522dddww8w42e403376a410e';
// Token(令牌)
$token = 'Yunfeit';
// EncodingAESKey(消息加解密密钥)
$encodingAESKey = '072vHYArTp33eFwznlSvTRvuyOTe5YME1vxSoyZbzaV';
// 这是使用了Memcached来保存access_token
$m = new Memcached();
$m->addServer('localhost', 11211);
// wechat模块 - 处理用户发送的消息和回复消息
$wechat = new Wechat(array(
'appId' => $appId,
'token' => $token,
'encodingAESKey' => $encodingAESKey
));
// api模块 - 包含各种系统主动发起的功能
$api = new Api(
array(
'appId' => $appId,
'appSecret' => $appSecret,
'get_access_token' => function() use ($m) {
// 用户需要自己实现access_token的返回
return $m->get('access_token');
},
'save_access_token' => function($token) use ($m) {
// 用户需要自己实现access_token的保存
$m->set('access_token', $token, 0);
},
'get_jsapi_ticket' => function() use ($m) {
// 可选:用户需要自己实现jsapi_ticket的返回(若使用get_jsapi_config,则必须定义)
return $m->get('jsapi_ticket');
},
'save_jsapi_ticket' => function($jsapi_ticket) use ($m) {
// 可选:用户需要自己实现jsapi_ticket的保存(若使用get_jsapi_config,则必须定义)
$m->set('jsapi_ticket', $jsapi_ticket, 0);
}
)
);
// 获取微信消息
$msg = $wechat->serve();
// 被动回复用户消息
$wechat->reply('这是我被动发送的消息!');
// 主动发送文本消息
$api->send($msg->FromUserName, '这是我主动发送的消息!');
所有Api模块的接口返回值格式为: array($err, $data);, (*23)
$err为错误信息, $data为正确处理返回的数据, (*24)
可用list接收:, (*25)
list($err, $kf_list) = $api->get_kf_list();
if (is_null($err)) {
// 接口正确返回处理
} else {
// 接口错误返回处理
}
官方wiki, (*26)
$api->send($msg->FromUserName, 'heheh');
// 或者
$api->send($msg->FromUserName, array(
'type' => 'text',
'content' => 'hello world!',
'kf_account' => 'test1@kftest' // 可选(指定某个客服发送, 会显示这个客服的头像)
));
$api->send($msg->FromUserName, array(
'type' => 'image',
'media_id' => 'Uq7OczuEGEyUu--dYjg7seTm-EJTa0Zj7UDP9zUGNkVpjcEHhl7tU2Mv8mFRiLKC',
'kf_account' => 'test1@kftest' // 可选(指定某个客服发送, 会显示这个客服的头像)
));
$api->send($msg->FromUserName, array(
'type' => 'voice',
'media_id' => 'rVT43tfDwjh4p1BV2gJ5D7Zl2BswChO5L_llmlphLaTPytcGcguBAEJ1qK4cg4r_',
'kf_account' => 'test1@kftest' // 可选(指定某个客服发送, 会显示这个客服的头像)
));
$api->send($msg->FromUserName, array(
'type' => 'video',
'media_id' => 'yV0l71NL0wtpRA8OMX0-dBRQsMVyt3fspPUzurIS3psi6eWOrb_WlEeO39jasoZ8',
'thumb_media_id' => '7ct_DvuwZXIO9e9qbIf2ThkonUX_FzLAoqBrK-jzUboTYJX0ngOhbz6loS-wDvyZ', // 可选(无效, 官方文档好像写错了)
'title' => '视频消息的标题', // 可选
'description' => '视频消息的描述', // 可选,
'kf_account' => 'test1@kftest' // 可选(指定某个客服发送, 会显示这个客服的头像)
));
$api->send($msg->FromUserName, array(
'type' => 'music',
'title' => '音乐标题', //可选
'description' => '音乐描述', //可选
'music_url' => 'http://me.diary8.com/data/music/2.mp3', //可选
'hqmusic_url' => 'http://me.diary8.com/data/music/2.mp3', //可选
'thumb_media_id' => 'O39wW0ZsXCb5VhFoCgibQs5PupFb6VZ2jH5A8gHUJCJz2Qmkrb7objoTue7bGTGQ',
'kf_account' => 'test1@kftest' // 可选(指定某个客服发送, 会显示这个客服的头像)
));
$api->send($msg->FromUserName, array(
'type' => 'news',
'articles' => array(
array(
'title' => '图文消息标题1', //可选
'description' => '图文消息描述1', //可选
'picurl' => 'http://me.diary8.com/data/img/demo1.jpg', //可选
'url' => 'http://www.example.com/' //可选
),
array(
'title' => '图文消息标题2',
'description' => '图文消息描述2',
'picurl' => 'http://me.diary8.com/data/img/demo2.jpg',
'url' => 'http://www.example.com/'
),
array(
'title' => '图文消息标题3',
'description' => '图文消息描述3',
'picurl' => 'http://me.diary8.com/data/img/demo3.jpg',
'url' => 'http://www.example.com/'
)
),
'kf_account' => 'test1@kftest' // 可选(指定某个客服发送, 会显示这个客服的头像)
));
官方wiki, (*27)
$api->add_kf('test1234@微信号', '客服昵称', '客服密码');
$api->update_kf('test1234@微信号', '客服昵称', '客服密码');
$api->set_kf_avatar('GB2@gbchina2000', '/website/wx/demo/test.jpg');
$api->del_kf('test1234@微信号');
$api->get_kf_list();
$api->get_online_kf_list();
$api->get_kf_records(1439348167, 1439384060, 1, 10);
$api->create_kf_session('ocNtAt_K8nRlAdmNEo_R0WVg_rRw', 'test1@微信号', '小明请求接入会话!');
$api->close_kf_session('ocNtAt_K8nRlAdmNEo_R0WVg_rRw', 'test1@微信号', '与小明的回话已关闭!');
$api->get_kf_session('ocNtAt_K8nRlAdmNEo_R0WVg_rRw');
$api->get_kf_session_list('test1@微信号');
$api->get_waitcase_list();
官方wiki, (*28)
$api->upload_media('image', '/data/img/fighting.jpg');
$api->upload_media('voice', '/data/img/song.amr');
$api->upload_media('video', '/data/img/go.mp4');
$api->upload_media('thumb', '/data/img/sky.jpg');
$api->get_media('UNsNhYrHG6e0oUtC8AyjCntIW1JYoBOmmwvM4oCcxZUBQ5PDFgeB9umDhrd9zOa-');
header('Content-type: image/jpg');
list($err, $data) = $api->download_media('UNsNhYrHG6e0oUtC8AyjCntIW1JYoBOmmwvM4oCcxZUBQ5PDFgeB9umDhrd9zOa-');
echo $data;
// 新增图片素材
list($err, $res) = $api->add_material('image', '/website/me/data/img/fighting.jpg');
// 新增音频素材
list($err, $res) = $api->add_material('voice', '/data/img/song.amr');
// 新增视频素材
list($err, $res) = $api->add_material('video', '/website/me/data/video/2.mp4', '视频素材的标题', '视频素材的描述');
// 新增略缩图素材
list($err, $res) = $api->add_material('thumb', '/data/img/sky.jpg');
$api->add_news(array(
array(
'title' => '标题',
'thumb_media_id' => '图文消息的封面图片素材id(必须是永久mediaID)',
'author' => '作者',
'digest' => '图文消息的摘要,仅有单图文消息才有摘要,多图文此处为空',
'show_cover_pic' => '是否显示封面,0为false,即不显示,1为true,即显示',
'content' => '图文消息的具体内容,支持HTML标签,必须少于2万字符,小于1M,且此处会去除JS',
'content_source_url' => '图文消息的原文地址,即点击“阅读原文”后的URL'
),
array(
'title' => '这是图文的标题',
'thumb_media_id' => 'BZ-ih-dnjWDyNXjai6i6sdvxOoXOHr9wO0pgMhcZR8g',
'author' => '这是图文的作者',
'digest' => '',
'show_cover_pic' => true,
'content' => '这是图文消息的具体内容',
'content_source_url' => 'http://www.baidu.com/'
)
));
list($err, $res) = $api->update_news('BZ-ih-dnjWDyNXjai6i6sZp22xhHu6twVYKNPyl77Ms', array(
'title' => '标题',
'thumb_media_id' => 'BZ-ih-dnjWDyNXjai6i6sdvxOoXOHr9wO0pgMhcZR8g',
'author' => '作者',
'digest' => '图文消息的摘要',
'show_cover_pic' => true,
'content' => '图文消息的具体内容',
'content_source_url' => 'http://www.diandian.com/'
), 1);
// 获取图片、音频、略缩图素材
// 返回素材的内容,可保存为文件或直接输出
header('Content-type: image/jpg');
list($err, $data) = $api->get_material('BZ-ih-dnjWDyNXjai6i6sdvxOoXOHr9wO0pgMhcZR8g');
echo $data;
// 获取视频素材
// 返回带down_url的json字符串
list($err, $data) = $api->get_material('BZ-ih-dnjWDyNXjai6i6sbOICualzdwwnWWBqxW39Xk');
var_dump(json_decode($data));
// 获取图文素材
// 返回图文的json字符串
list($err, $data) = $api->get_material('BZ-ih-dnjWDyNXjai6i6sdvxOoXOHr9wO0pgMhcZR8g');
var_dump(json_decode($data));
list($err, $res) = $api->del_material('BZ-ih-dnjWDyNXjai6i6sbOICualzdwwnWWBqxW39Xk');
if (is_null($err)) {
// 删除成功
}
$api->get_material_count();
$api->get_materials('image', 0, 20);
$api->get_materials('voice', 0, 20);
$api->get_materials('video', 0, 20);
$api->get_materials('thumb', 0, 20);
官方wiki, (*29)
$api->create_menu('
{
"button":[
{
"type":"click",
"name":"主菜单1",
"key":"V1001_TODAY_MUSIC"
},
{
"name":"主菜单2",
"sub_button":[
{
"type":"click",
"name":"点击推事件",
"key":"click_event1"
},
{
"type":"view",
"name":"跳转URL",
"url":"http://www.example.com/"
},
{
"type":"scancode_push",
"name":"扫码推事件",
"key":"scancode_push_event1"
},
{
"type":"scancode_waitmsg",
"name":"扫码带提示",
"key":"scancode_waitmsg_event1"
}
]
},
{
"name":"主菜单3",
"sub_button":[
{
"type":"pic_sysphoto",
"name":"系统拍照发图",
"key":"pic_sysphoto_event1"
},
{
"type":"pic_photo_or_album",
"name":"拍照或者相册发图",
"key":"pic_photo_or_album_event1"
},
{
"type":"pic_weixin",
"name":"微信相册发图",
"key":"pic_weixin_event1"
},
{
"type":"location_select",
"name":"发送位置",
"key":"location_select_event1"
}
]
}
]
}');
$api->get_menu();
$api->delete_menu();
$api->get_selfmenu();
官方wiki, (*30)
使用前请确认,初始化Api时,已填写并实现了get_jsapi_ticket和save_jsapi_ticket, (*31)
$api->get_jsapi_config();
$api->get_jsapi_config('http://www.baidu.com/');
$api->get_jsapi_config('', 'json');
$api->get_jsapi_config('', 'jsonp');
$api->get_jsapi_config('', 'jsonp', 'callback');
官方wiki, (*32)
list($err, $data) = $api->create_qrcode(1234); // 创建一个永久二维码 list($err, $data) = $api->create_qrcode(1234, 100); //创建一个临时二维码,有效期100秒
$api->get_qrcode_url('gQH58DoAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xLzQweUctT2psME1lcEJPYWJkbUswAAIEApzVVQMEZAAAAA==');
list($err, $data) = $api->get_qrcode('gQGa8ToAAAAAAAAAASxodHRwOi8vd2VpeGluLnFxLmNvbS9xLzlVeXJZWS1seGNlODZ2SV9XMkMwAAIEo5rVVQMEAAAAAA==');
header('Content-type: image/jpg');
echo $data;
list($err, $data) = $api->shorturl('http://me.diary8.com/category/web-front-end.html');
echo $data->short_url;
包含:用户分组管理、设置用户备注名、获取用户基本信息、获取用户列表、网页授权获取用户基本信息, (*33)
官方wiki, (*34)
list($err, $data) = $api->create_group('新的一个分组');
echo $data->group->id;
list($err, $data) = $api->get_groups();
foreach ($data->groups as $group) {
var_dump($group);
}
list($err, $data) = $api->get_user_group('ocNtAt0YPGDme5tJBXyTphvrQIrc');
echo $data->groupid;
$api->update_group(100, '自定义分组了');
$api->update_user_group('ocNtAt0YPGDme5tJBXyTphvrQIrc', 100);
$api->batchupdate_user_group(array(
'ocNtAt0YPGDme5tJBXyTphvrQIrc',
'ocNtAt_TirhYM6waGeNUbCfhtZoA',
'ocNtAt_K8nRlAdmNEo_R0WVg_rRw'
), 100);
$api->delete_group(102);
$api->update_user_remark('ocNtAt0YPGDme5tJBXyTphvrQIrc', '用户的备注名');
$api->get_user_info('ocNtAt_K8nRlAdmNEo_R0WVg_rRw');
$api->get_user_info('ocNtAt_K8nRlAdmNEo_R0WVg_rRw', 'zh_TW');
$api->get_user_list();
$api->get_user_list('ocNtAt_TirhYM6waGeNUbCfhtZoA');
有两种授权类型:, (*35)
snsapi_base 静默授权,用户无感知,但只能获取到openid
snsapi_userinfo 可以获得openid、昵称、性别、所在地等更详细的信息,但首次授权会跳转微信的一个授权页面,用户点击同意后授权成功两种授权流程使用说明:, (*36)
demo见项目内 demo/snsapi/, (*37)
通过 get_authorize_url 生成获取用户授权的链接,用户打开该链接后会跳转到 回调地址页面, (*38)
$api->get_authorize_url('授权类型', '回调地址');
$api->get_authorize_url('snsapi_base','http://wx.diary8.com/demo/snsapi/callback_snsapi_base.php');
$api->get_authorize_url('snsapi_userinfo', 'http://wx.diary8.com/demo/snsapi/callback_snsapi_userinfo.php');
在 回调地址页面 通过 get_userinfo_by_authorize 获取用户信息, (*39)
list($err, $user_info) = $api->get_userinfo_by_authorize('snsapi_base');
if ($user_info !== null) {
var_dump($user_info);;
} else {
echo '授权失败!';
}
list($err, $user_info) = $api->get_userinfo_by_authorize('snsapi_userinfo');
if ($user_info !== null) {
var_dump($user_info);;
} else {
echo '授权失败!';
}
官方wiki, (*40)
官方SDK, (*41)
支付过程中SDK使用流程:, (*42)
openid
wxPayUnifiedOrder 生成预订单getWxPayJsApiParameters 生成jsapi支付的参数,作为js调用支付接口的参数eg: api, (*43)
/* @var $cache \yii\redis\cache */
$cache = \Yii::$app->cache;
$api = new Api([
'appId' => 'wx312273d5za28s525', //AppID
'appSecret' => '7d8e268465d6ec7ch2f4ed2364h5ef32', //AppSecret
'mchId' => '1633246021', //微信支付商户号
'key' => '613A60282Aa87E2B1A22E3A3DFD9AE32A', //微信商户API密钥
'get_access_token' => function() use ($cache) {
return $cache->get('WE_CHAT_SDK_ACCESS_TOKEN');
},
'save_access_token' => function($token) use ($cache) {
$cache->set('WE_CHAT_SDK_ACCESS_TOKEN', $token);
}
]);;
eg: 页面内调起微信支付, (*44)
// 获取用户的openid
list($err, $user_info) = $api->get_userinfo_by_authorize('snsapi_base');
if ($user_info == null) {
$url = $api->get_authorize_url('snsapi_base', Yii::$app->request->absoluteUrl);
return $this->controller->redirect($url);
}
// 生成预订单
$wxOrder = $api->wxPayUnifiedOrder([
'trade_type' => 'JSAPI',
'out_trade_no' => '100002',
'body' => '新鲜大白菜',
'total_fee' => 100, // 单位是分
//'time_expire' => date('YmdHis', (int)$order['created_at'] + (int)$order['timeout']),
'notify_url' => 'http://example.com/we-chat-pay/asyn-notify',
'openid' => $user_info->openid,
]);
// 判断预订单是否生成成功
if ($wxOrder['return_code'] == 'SUCCESS' && $wxOrder['result_code'] == 'SUCCESS') {
// 成功处理,获取JSAPI支付的参数
$jsApiParams = $api->getWxPayJsApiParameters($wxOrder['prepay_id']);
} else {
// 失败处理...
}
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>微信支付</title>
<script type="text/javascript">
function jsApiCall() {
WeixinJSBridge.invoke(
'getBrandWCPayRequest',
<?= $jsApiParams ?>,
function(res){
alert(JSON.stringfy(res));
WeixinJSBridge.log(res.err_msg);
alert(res.err_code+res.err_desc+res.err_msg);
}
);
}
if (typeof WeixinJSBridge == 'undefined'){
if( document.addEventListener ){
document.addEventListener('WeixinJSBridgeReady', jsApiCall, false);
}else if (document.attachEvent){
document.attachEvent('WeixinJSBridgeReady', jsApiCall);
document.attachEvent('onWeixinJSBridgeReady', jsApiCall);
}
}else{
jsApiCall();
}
</script>
</head>
</html>
eg: 处理微信支付结果异步回调, (*45)
// 处理微信支付异步通知 // $res: 是否支付成功 // $notifyData: 异步通知的原始数据 // $replyData: 回复微信异步通知的数据 list($res, $notifyData, $replyData) = $api->progressWxPayNotify(); // 处理业务逻辑 // ... // 回复微信 $api->replyWxPayNotify($replyData); exit();
redirect_uri参数错误
开发者中心->功能服务[网页账号:网页授权获取用户基本信息]->修改->填写回调的域名当前页面的URl未注册
微信支付->公众号支付填写支付授权目录
HTTP_RAW_POST_DATA,这里使用 php://input
官方wiki, (*46)
微信App支付与微信公众号支付类似:, (*47)
支付过程中SDK使用流程:, (*48)
wxPayUnifiedOrder 生成预订单getWxPayAppApiParameters 生成App支付的参数,作为自己App调起微信打开支付界面的参数progressWxPayNotify 验证异步通知并做相应业务操作eg: 写个服务端接口[生成预订单,并得到App的支付参数] 供客户端App调用, (*49)
// 生成预订单 $wxOrder = $api->wxPayUnifiedOrder([ 'trade_type' => 'APP', 'out_trade_no' => '100002', 'body' => '新鲜大白菜', 'total_fee' => 100, // 单位是分 //'time_expire' => date('YmdHis', (int)$order['created_at'] + (int)$order['timeout']), 'notify_url' => 'http://example.com/we-chat-pay/asyn-notify', ]); // 判断预订单是否生成成功 if ($wxOrder['return_code'] == 'SUCCESS' && $wxOrder['result_code'] == 'SUCCESS') { // 成功处理,获取App支付的参数 $apiParams = $api->getWxPayAppApiParameters($wxOrder['prepay_id']); // 返回给app客户端 return json_encode($apiParams); } else { // 失败处理... }
# iOS调起微信支付 (微信官网的,未验证) PayReq *request = [[[PayReq alloc] init] autorelease]; request.partnerId = @"10000100"; request.prepayId= @"1101000000140415649af9fc314aa427"; request.package = @"Sign=WXPay"; request.nonceStr= @"a462b76e7436e98e0ed6e13c64b4fd1c"; request.timeStamp= @"1397527777"; request.sign= @"582282D72DD2B03AD892830965F428CB16E7A256"; [WXApi sendReq:request];
# android调起微信支付 (微信官网的,未验证) IWXAPI api; PayReq request = new PayReq(); request.appId = "wxd930ea5d5a258f4f"; request.partnerId = "1900000109"; request.prepayId= "1101000000140415649af9fc314aa427",; request.packageValue = "Sign=WXPay"; request.nonceStr= "1101000000140429eb40476f8896f4c9"; request.timeStamp= "1398746574"; request.sign= "7FFECB600D7157C5AA49810D2D8F28BC2811827B"; api.sendReq(req);
eg: 处理微信支付结果异步回调, (*50)
// 处理微信支付异步通知 // $res: 是否支付成功 // $notifyData: 异步通知的原始数据 // $replyData: 回复微信异步通知的数据 list($res, $notifyData, $replyData) = $api->progressWxPayNotify(); // 处理业务逻辑 // ... // 回复微信 $api->replyWxPayNotify($replyData); exit();
MIT, (*51)