Blogger Information
Blog 57
fans 3
comment 0
visits 60510
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
商城项目-微信支付流程
岂几岂几
Original
1566 people have browsed it

商城项目-微信支付流程

  • 没有企业APPID, 只记录老师视频中的实现过程

1. 微信文档说明

  • 微信支付文档很乱, 新的旧的方式掺杂在一起. 在微信支付的首页, 点击”产品中心”, 在”支付产品”点击自己希望接入微信支付的应用场景(课程实例是PC站接入, 所以选择Native支付).

  • 微信支付根据不同的支付场景, 提供不同的接入方式. 微信支付场景.

    • 付款码支付: 生成永久付款二维码供别人扫码支付.
    • JSAPI支付: 在公众号中接入支付.
    • 小程序支付: 微信小程序中支付.
    • Native支付: PC端网站接入支付, 即生成临时付款二维码, 用户扫码支付.
    • APP支付: 安卓和IOS端的APP接入支付.
    • H5支付: 手机/平板等移动端的浏览器中接入支付.
  • 点击Native支付中的”开发文档”, 在Native支付中的开发文档中, 这里是微信推荐的支付页面样式, 并提供了素材下载. 开发模式一已不被推荐, 开发模式二是老师推荐的方式. API列表新手直接放弃阅读, 难度很大, 坑也多; 作为替代方案, 使用新提供的sdk方式实现模式二接入相对来说更加简单一些.

  • 开始之前, 先按照开发步骤中的流程, 申请到APPID, MCHID(商户号), KEY和APPSECRET.

2. 把Native支付示例嵌入到laravel项目中

2.1 调通微信支付并从微信获取支付二维码

  • sdk方式中下载PHP版本的SDK包, 解压到laravel的vendor目录(假设重命名为wxpay). 在 /wxpay/example 中有各种支付场景的接入方式的示例( index.php 文件中列出了各种接入方式的链接). 其中, Native方式接入的示例文件是 /wxpay/example/native.php .

  • /wxpay/example/native.php 中把模式二用到的代码拷贝到生成二维码的控制器方法中, 并改对引用到的文件路径(注意, 引入的文件中, 还引入了其他文件, 引入其他文件的也要改), 修改代码中微信支付相关的类为完全限定名称方式的调用(都在全局命名空间中).

    • 控制器方法中的路径修改和微信支付相关类改为完全限定名称调用
  1. public function pay() {
  2. // __DIR__ = X:/.../laravel/app/Http/Controllers/front;
  3. // 用相对路径导航到wxpay根目录
  4. $wxpayPath = __DIR__ . "/../../../../vendor/wxpay/";
  5. // 微信二维码支付需要用到的文件
  6. require_once $wxpayPath . "lib/WxPay.Api.php";// 改成
  7. require_once $wxpayPath . "/example/WxPay.NativePay.php";
  8. /* 改成完全限定名称 */
  9. $notify = new \NativePay();
  10. //模式二
  11. /**
  12. * 流程:
  13. * 1、调用统一下单,取得code_url,生成二维码
  14. * 2、用户扫描二维码,进行支付
  15. * 3、支付完成之后,微信服务器会通知支付成功
  16. * 4、在支付成功通知中需要查单确认是否真正支付成功(见:notify.php)
  17. */
  18. /* 改成完全限定名称 */
  19. $input = new \WxPayUnifiedOrder();
  20. // 模式二的其他业务逻辑
  21. $input->SetBody("test");
  22. $input->SetAttach("test");
  23. // 这里要改成站点自己生成的订单号
  24. $input->SetOut_trade_no("sdkphp123456789".date("YmdHis"));
  25. // 设置支付金额(单位: 分)
  26. $input->SetTotal_fee("1");
  27. $input->SetTime_start(date("YmdHis"));
  28. // 二维码有效时长
  29. $input->SetTime_expire(date("YmdHis", time() + 600));
  30. $input->SetGoods_tag("test");
  31. // 处理微信返回的用户支付结果(xml文件格式数据)的请求地址.
  32. $input->SetNotify_url("http://www.myweb.com/notify.php");
  33. // 设置支付场景(Native)
  34. $input->SetTrade_type("NATIVE");
  35. $input->SetProduct_id("123456789");
  36. $result = $notify->GetPayUrl($input);
  37. $data['code_url'] = '';
  38. // 调通的情况下, 把二维码地址发送到视图中渲染;
  39. if($result['return_code'] == 'SUCCESS') $url2 = $result["code_url"];
  40. // 调试时打印输出看看效果
  41. var_dump($result);
  42. return view('/front/shop/pay', $data);
  43. }
  • SDK中的文件引入路径修改- /vendor/wxpay/example/WxPay.NativePay.php
  1. require_once __DIR__ . "/../lib/WxPay.Api.php";
  2. require_once __DIR__ . "/WxPay.Config.php";
  3. require_once __DIR__ . '/log.php';
  4. // ......
  • SDK中的文件引入路径修改- /vendor/wxpay/example/WxPay.Config.php
  1. require_once __DIR__ . "/../lib/WxPay.Config.Interface.php";
  • SDK中的日志方法修改- /vendor/wxpay/example/log.php
  1. // 注释写日志方法
  2. public static function ERROR($msg)
  3. {
  4. // 修改为直接打印错误并返回.
  5. echo $mes;return;
  6. $debugInfo = debug_backtrace();
  7. $stack = "[";
  8. foreach($debugInfo as $key => $val){
  9. if(array_key_exists("file", $val)){
  10. $stack .= ",file:" . $val["file"];
  11. }
  12. if(array_key_exists("line", $val)){
  13. $stack .= ",line:" . $val["line"];
  14. }
  15. if(array_key_exists("function", $val)){
  16. $stack .= ",function:" . $val["function"];
  17. }
  18. }
  19. $stack .= "]";
  20. //self::$instance->write(8, $stack . $msg);
  21. }
  • 做完上述修改后, 调通该做的工作基本完成, 此时要把申请到的4个配置值设置到 WxPay.Config.php 中.

    • 把申请到的APPID, MCHID(商户号), KEY和APPSECRET值添加到配置文件 WxPay.Config.php
  1. /**
  2. * TODO: 修改这里配置为您自己申请的商户信息
  3. * 微信公众号信息配置
  4. *
  5. * APPID:绑定支付的APPID(必须配置,开户邮件中可查看)
  6. *
  7. * MCHID:商户号(必须配置,开户邮件中可查看)
  8. *
  9. */
  10. public function GetAppId()
  11. {
  12. // 返回APPID
  13. return '';
  14. }
  15. public function GetMerchantId()
  16. {
  17. // 返回MCHID, 即商户号.
  18. return '';
  19. }
  20. // ......
  21. /*
  22. * KEY:商户支付密钥,参考开户邮件设置(必须配置,登录商户平台自行设置), 请妥善保管, 避免密钥泄露
  23. * 设置地址:https://pay.weixin.qq.com/index.php/account/api_cert
  24. *
  25. * APPSECRET:公众帐号secert(仅JSAPI支付的时候需要配置, 登录公众平台,进入开发者中心可设置), 请妥善保管, 避免密钥泄露
  26. * 获取地址:https://mp.weixin.qq.com/advanced/advanced?action=dev&t=advanced/dev&token=2005451881&lang=zh_CN
  27. * @var string
  28. */
  29. public function GetKey()
  30. {
  31. // 返回KEY
  32. return '';
  33. }
  34. public function GetAppSecret()
  35. {
  36. // 返回APPSECRET
  37. return '';
  38. }
  39. // ......
  • 当前实例没有设置证书, 所以需要修改 WxPay.Api.php 中的配置, 把相关配置设置成不需要证书:
  1. private static function postXmlCurl($config, $xml, $url, $useCert = false, $second = 30) {
  2. // ......
  3. // 原文件中的567-568行
  4. curl_setopt($ch,CURLOPT_SSL_VERIFYPEER,FALSE); // 设置为FALSE表示不需要证书
  5. curl_setopt($ch,CURLOPT_SSL_VERIFYHOST,0); // 设置为0表示不执行严格校验, 默认值是2, 严格校验.
  6. // ......
  7. }
  • 经过上面一通操作后, var_dump($result) 就有值打印出来了, 即设置完成. 创建一个控制器方法, 复制 /wxpay/example/qrcode.php 中的逻辑到方法中(注意修改相关文件的引入路径), 供前端 <img> 元素获取生成的二维码图片

    • 生成二维码的控制器方法()
  1. // 获取二维码的控制器方法
  2. public function createQrccode() {
  3. $wxpayPath = __DIR__ . '/../../../../vendor/wxpay/';
  4. require_once $wxpayPath . 'example/phpqrccode/phpqrccode.php';
  5. $url = urldecode($_GET['data']);
  6. if(substr($url, 0, 6) == 'weixin') {
  7. /* 改成完全限定名称 */
  8. \QRcode::png($url);
  9. } else {
  10. header('HTTP/1.1 404 Not Found');
  11. }
  12. }
  • 前端 <img> 元素获取二维码图片(记得设置路由)
    1. <img src="/shop/qrccode?data=<?php echo urlencode($url2); ?>" alt="" class="qrccode">
  • 到这里, 应该能正常显示二维码了.

tips: 在SDK中, 没有移动端浏览器支付的实例, 只要设置该方法传入参数”mweb”即可: $input->SetTrade_type("mweb"); .

2.2 获取从微信返回的支付结果

  • 用户支付完成后, 微信会发送一个post请求, 发送用户支付结果(xml文件格式数据). 接收该post请求的url地址, 是在调通微信支付时设置的: $input->SetNotify_url("处理微信返回的用户支付结果的请求地址"); . 该请求必须能通过外网访问.
  • 支付结果信息中包含这些内容. 其中:

    • openid : 谁付的钱.
    • out_trade_no : 站点生成的订单号.
    • result_code : 支付结果, SUCCES(成功)/FEIL().
    • total_fee : 支付的金额(单位: 分).
    • transaction_id : 微信内部的交易号.
  • 支付界面(二维码扫码页面)需要设置一个定时器, 定时去查询订单的支付状态, 当支付状态为”已支付”时, 就使用调用 window.parent.location.reload() 的js表达式调用父页面的js方法, 完成父页面的刷新或跳转(到支付成功页面).

Correction status:Uncorrected

Teacher's comments:
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post