Java PHP C# Python Node.js Android Objective-C

0. 开通渠道

BeeCloud支持线上线下各种场景的支付解决方案,本文档以场景的形式展示如何使用BeeCloud开发,完成支付技术的接入。

0.1 开通渠道

官方渠道申请指导:
微信APP的申请: 这里
微信公众号的申请: 这里
支付宝APP/PC网页/移动网页的申请: 这里

0.2 渠道参数配置

微信APP参数配置: 这里
微信公众号参数配置: 这里
支付宝APP/PC网页/移动网页参数配置: 这里
支付宝RSA秘钥配置: 这里

1. SDK开发

1.1 SDK安装和注册

1.1.1 SDK安装

SDK下载地址 这里

1.1.2 在代码中注册BeeCloud

  1. 注册开发者:猛击这里注册成为BeeCloud开发者, 并完成企业认证
  2. 注册应用:使用注册的账号登陆控制台后,点击“创建新的支付应用"创建新应用
  3. 在新创建的支付应用下 应用设置下 基本信息设置中 获取APP IDAPP SecretMaster SecretTest Secret,其中Test Secret在控制台的test模式下获取。
  4. 在代码中注册
Java PHP C# Python Node.js Android Objective-C

注册使用如下代码:

    //LIVE模式使用方法
    BeeCloud.registerApp(appId, testSecret, appSecret, masterSecret);
    //LIVE模式中的testSecret可为null
    //默认开启LIVE模式

    //测试模式使用方法
    BeeCloud.registerApp(appId, testSecret, **appSecret**, **masterSecret**);
    //测试模式中的appSecret、masterSecret可为null
    //设置sandbox属性为true,开启测试模式
    BeeCloud.setSandbox(true);
    \beecloud\rest\api::registerApp('app id', 'app secret', 'master secret', 'test secret');
    //不使用namespace的用户
    BCRESTApi::registerApp('app id', 'app secret', 'master secret', 'test secret')

    //LIVE模式使用方法(也可不设置,默认为为LIVE模式)
    \beecloud\rest\api::setSandbox(false);
    //不使用namespace的用户
    BCRESTApi::setSandbox(false);

    //测试模式使用方法
    \beecloud\rest\api::setSandbox(true);
    //不使用namespace的用户
    BCRESTApi::setSandbox(true);
    //请注意各个参数一一对应
    BeeCloud.BeeCloud.registerApp(appID, appSecret, masterSecret, testSecret);

    //设置生产模式,真实货币交易(也可不设置,默认为上线模式)
    BeeCloud.BeeCloud.setTestMode(false);
    //设置当前为测试模式
    BeeCloud.BeeCloud.setTestMode(true);
                    
    bc_app = BCApp()
    bc_app.app_id = 'app_id'
    bc_app.app_secret = 'app_secret'
    bc_app.master_secret = 'master_secret'
    # 如果需要开启测试模式
    # bc_app.is_test_mode = True
    # bc_app.test_secret = 'test_secret'

    # 如果用到支付退款和打款
    bc_pay = BCPay()
    bc_pay.register_app(bc_app)

    # 如果需要查询功能
    bc_query = BCQuery()
    bc_query.register_app(bc_app)
                    
    const API = new BCRESTAPI();
    API.registerApp(APP_ID,APP_SECRET,MASTER_SECRET,TEST_SECRET);
    API.setSandbox(true);//开启测试模式 不设置就是不开启
                    
    BeeCloud.setAppIdAndSecret("appId", "appSecret");

    // 如果需要开启测试模式
    // BeeCloud.setSandbox(true);
    // BeeCloud.setAppIdAndSecret("appId", "testSecret");
                    
    //注意:sdk的demo中包含apple pay的例子,不能直接在模拟器上运行,请在真机上运行,
    //如果要在模拟器上运行,请删除项目中(非物理文件夹)`BCPaySDK`文件夹下面`Channel`文件夹下的`ApplePay`文件夹即可

    //初始化分为生产模式(LiveMode)、沙箱环境(SandboxMode);沙箱测试模式下不产生真实交易
    //开启生产环境
    [BeeCloud initWithAppID:@"BeeCloud AppId" andAppSecret:@"BeeCloud App Secret"];


    //开启沙箱测试环境
    [BeeCloud initWithAppID:@"BeeCloud AppId" andAppSecret:@"BeeCloud Test Secret"];
    [BeeCloud setSandboxMode:YES];
    或者
    [BeeCloud initWithAppID:@"BeeCloud AppId" andAppSecret:@"BeeCloud Test Secret" sandbox:YES];


    //查看当前模式
    // 返回YES代表沙箱测试模式;NO代表生产模式
    [BeeCloud getCurrentMode];


    //初始化官方微信支付
    //如果您使用了微信支付,需要用微信开放平台Appid初始化。
    [BeeCloud initWeChatPay:@"微信开放平台appid"];


    //handleOpenUrl
    //为保证从支付宝,微信返回本应用,须绑定openUrl. 用于iOS9之前版本
    - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
        if (![BeeCloud handleOpenUrl:url]) {
            //handle其他类型的url
        }
        return YES;
    }
    //iOS9之后apple官方建议使用此方法
    - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<NSString *,id> *)options {
        if (![BeeCloud handleOpenUrl:url]) {
        //handle其他类型的url
        }
        return YES;
        }
                    

1.2 网页上收款

1.2.1 流程概述

步骤①:(从网页服务器端)发送订单信息

步骤②:收到BeeCloud返回的渠道支付地址(比如支付宝的收银台)

步骤③:将支付地址展示给用户进行支付

步骤④:用户支付完成后通过一开始发送的订单信息中的return_url来返回商户页面

此时商户的网页需要做相应界面展示的更新(比如告诉用户"支付成功"或"支付失败”)。不允许使用同步回调的结果来作为最终的支付结果,因为同步回调有极大的可能性出现丢失的情况(即用户支付完没有执行return url,直接关掉了网站等等),最终支付结果应以下面的异步回调为准。

步骤⑤:(在商户后端服务端)处理异步回调结果(Webhook)

付款完成之后,根据客户在BeeCloud后台的设置,BeeCloud会向客户服务端发送一个Webhook请求,里面包括了数字签名,订单号,订单金额等一系列信息。客户需要在服务端依据规则要验证数字签名是否正确,购买的产品与订单金额是否匹配,这两个验证缺一不可。验证结束后即可开始走支付完成后的逻辑。

1.2.2 网页上实现支付宝收款

1.2.2.1 支付宝收银台收款

  1. 用户发起付款请求
  2. 系统生成付款订单,包括订单号,订单标题,金额等信息
  3. 将订单存入自己系统数据库中,标记订单为未支付
  4. 调用BeeCloud SDK中的支付接口,请求支付宝
  5. 支付宝返回一个url或者html
  6. 通过跳转到url或者将html输出到页面进而打开支付宝收银台页面,用户登录支付宝付款
  7. 支付完成,用户跳转到设置的return url地址
  8. 支付成功,webhook通知商户服务器,商户校验后将自己数据库中的订单标记为支付成功
Java PHP C# Python Node.js Android Objective-C

支付宝收银台收款代码示例:

    BCOrder bcOrder = new BCOrder('渠道code', '金额', '订单编号', '订单标题');//设定订单信息
    bcOrder.setBillTimeout(360);//设置订单超时时间
    bcOrder.setReturnUrl(aliReturnUrl);//设置return url
    try {
        bcOrder = BCPay.startBCPay(bcOrder);
        //out.println(bcOrder.getObjectId());
        out.println(bcOrder.getHtml()); // 输出支付宝收银台到页面
    } catch (BCException e) {
        log.error(e.getMessage(), e);
        out.println(e.getMessage());
    }
    try {
        $data = array(
            'timestamp' => time() * 1000,
            'channel' => 'ALI_WEB', //渠道类型
            'title' => '支付宝及时到账支付测试',   //订单标题
            'bill_no' => "bcdemo" . time(),    //订单编号
            'total_fee' => 1, //订单金额(int 类型) ,单位分
            'return_url' => 'https://beecloud.cn', //渠道类型:ALI_WEB、ALI_QRCODE、UN_WEB、JD_WAP、JD_WEB时为必填
            'bill_timeout' => 360, //京东(JD*)不支持该参数
        );
        $result = \beecloud\rest\api::bill($data);
        //不使用namespace的用户
        //$result = BCRESTApi::bill($data);
        if(isset($result->url)){
            header("Location:$result->url");
        }else if(isset($result->html)) {
            echo $result->html;
        }
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    BCBill bill = new BCBill('渠道code', '金额', '订单号', '订单标题');

    //支付渠道处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径,中间请勿有#,?等字符,必填参数
    bill.returnUrl = "http://localhost:50003/return_ali_url.aspx";

    try
    {
        BCBill resultBill = BCPay.BCPayByChannel(bill);

        //Response.Write("<span style='color:#00CD00;font-size:20px'>" + resultBill.html + "</span><br/>");
        Response.Redirect(resultBill.url); //跳转到支付宝的收款二维码页面
    }
    catch (Exception excption)
    {
        //错误处理
    }
                    
    req_params = BCPayReqParams()
    req_params.channel = 'ALI_WEB'
    req_params.title = u'支付测试'
    # 分为单位
    req_params.total_fee = 1
    req_params.bill_no = 'bill number'
    # 支付完成后的跳转页面
    req_params.return_url = 'http://your.return.url.cn/'
    result = bc_pay.pay(req_params)
    # 如果result.result_code为0表示请求成功
    # 然后对返回参数url重定向
                    
    //前端传参
    let data = {}, _this = this;
        data.channel = 'ALI_WEB';//根据不同场景选择不同的支付方式
        data.timestamp = new Date().valueOf();//时间戳,毫秒数
        data.total_fee = 1;//total_fee(int 类型) 单位分
        data.bill_no = `bcdemo${data.timestamp}`;//8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复
        data.title = `node${data.channel}test`;//title UTF8编码格式,32个字节内,最长支持16个汉字
        data.optional = {tag: 'msgtoreturn'};//用户自定义的参数,将会在webhook通知中原样返回,该字段主要用于商户携带订单的自定义数据
        data.bill_timeout = 360;//选填必须为非零正整数,单位为秒,建议最短失效时间间隔必须大于360秒,京东(JD*)不支持该参数。
        data.return_url = "https://beecloud.cn";//当channel参数为 ALI_WEB 或 ALI_QRCODE 或 UN_WEB 或 JD_WAP 或 JD_WEB时为必填

    //后端
    const BCRESTAPI = require('beecloud-node-sdk');
    const API = new BCRESTAPI();

    app.post('/api/bill', (req, res, next) => {
        API.bill(req.body).then((response) => {
            res.send(response);
        })
    })
                    

1.2.2.2 支付宝网页二维码收款

  1. 用户发起付款请求
  2. 系统生成付款订单,包括订单号,订单标题,金额等信息
  3. 将订单存入自己系统数据库中,标记订单为未支付
  4. 调用BeeCloud SDK中的支付接口,请求支付宝
  5. 支付宝返回一个url或者html
  6. 通过跳转到url或者将html输出到页面进而打开支付宝二维码的页面,用户扫码付款
  7. 支付完成,用户跳转到设置的return url地址
  8. 支付成功,webhook通知商户服务器,商户校验后将自己数据库中的订单标记为支付成功
Java PHP C# Python Node.js Android Objective-C

支付宝网页二维码收款代码示例:

    BCOrder bcOrder = new BCOrder(渠道code, 金额, 订单编号, 订单标题);//设定订单信息
    bcOrder.setBillTimeout(360);//设置订单超时时间
    bcOrder.setReturnUrl(aliReturnUrl);//设置return url
    try {
        bcOrder = BCPay.startBCPay(bcOrder);
        //out.println(bcOrder.getObjectId());
        out.println(bcOrder.getHtml()); // 输出支付宝收银台二维码到页面
    } catch (BCException e) {
        log.error(e.getMessage(), e);
        out.println(e.getMessage());
    }
    try {
        $data = array(
            'timestamp' => time() * 1000,
            'channel' => 'ALI_QRCODE', //渠道类型
            'title' => '支付宝网页二维码支付测试',   //订单标题
            'bill_no' => "bcdemo" . time(),    //订单编号
            'total_fee' => 1, //订单金额(int 类型) ,单位分
            //qr_pay_mode必填 二维码类型含义
            //0: 订单码-简约前置模式, 对应 iframe 宽度不能小于 600px, 高度不能小于 300px
            //1: 订单码-前置模式, 对应 iframe 宽度不能小于 300px, 高度不能小于 600px
            //3: 订单码-迷你前置模式, 对应 iframe 宽度不能小于 75px, 高度不能小于 75px
            'qr_pay_mode' => "0",
            'return_url' => 'https://beecloud.cn', //渠道类型:ALI_WEB、ALI_QRCODE、UN_WEB、JD_WAP、JD_WEB时为必填
            'bill_timeout' => 360, //京东(JD*)不支持该参数
        );
        $result = \beecloud\rest\api::bill($data);
        //不使用namespace的用户
        //$result = BCRESTApi::bill($data);
        if(isset($result->url)){
            header("Location:$result->url");
        }else if(isset($result->html)) {
            echo $result->html;
        }
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    BCBill bill = new BCBill('渠道code', '金额', '订单号', '订单标题');
    bill.qrPayMode = "0";

    //支付渠道处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径,中间请勿有#,?等字符,必填参数
    bill.returnUrl = "http://localhost:50003/return_ali_url.aspx";

    try
    {
        BCBill resultBill = BCPay.BCPayByChannel(bill);

        //Response.Write("<span style='color:#00CD00;font-size:20px'>" + resultBill.html + "</span><br/>");
        Response.Redirect(resultBill.url); //跳转到支付宝的收款二维码页面
    }
    catch (Exception excption)
    {
        Response.Write("<span style='color:#00CD00;font-size:20px'>" + excption.Message + "</span><br/>");
    }
                    
    req_params = BCPayReqParams()
    req_params.channel = 'ALI_QRCODE'
    req_params.title = u'支付测试'
    # 分为单位
    req_params.total_fee = 1
    req_params.bill_no = 'bill number'
    # 支付完成后的跳转页面
    req_params.return_url = 'http://your.return.url.cn/'
    result = bc_pay.pay(req_params)
    # 如果result.result_code为0表示请求成功
    # 然后对返回参数url重定向
                    
    //前端传参
    let data = {}, _this = this;
        data.channel = 'ALI_QRCODE';//根据不同场景选择不同的支付方式
        data.timestamp = new Date().valueOf();//时间戳,毫秒数
        data.total_fee = 1;//total_fee(int 类型) 单位分
        data.bill_no = `bcdemo${data.timestamp}`;//8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复
        data.title = `node${data.channel}test`;//title UTF8编码格式,32个字节内,最长支持16个汉字
        data.optional = {tag: 'msgtoreturn'};//用户自定义的参数,将会在webhook通知中原样返回,该字段主要用于商户携带订单的自定义数据
        data.bill_timeout = 360;//选填必须为非零正整数,单位为秒,建议最短失效时间间隔必须大于360秒,京东(JD*)不支持该参数。
        data.return_url = "https://beecloud.cn";//当channel参数为 ALI_WEB 或 ALI_QRCODE 或 UN_WEB 或 JD_WAP 或 JD_WEB时为必填

    //后端
    const BCRESTAPI = require('beecloud-node-sdk');
    const API = new BCRESTAPI();

    app.post('/api/bill', (req, res, next) => {
        API.bill(req.body).then((response) => {
            res.send(response);
        })
    })
                    

1.2.2.3 支付宝移动网页收款

  1. 用户发起付款请求
  2. 系统生成付款订单,包括订单号,订单标题,金额等信息
  3. 将订单存入自己系统数据库中,标记订单为未支付
  4. 调用BeeCloud SDK中的支付接口,请求支付宝
  5. 支付宝返回一个url或者html
  6. 通过跳转到url或者将html输出到页面进而打开支付宝二维码的页面,用户扫码付款
  7. 支付完成,用户跳转到设置的return url地址
  8. 支付成功,webhook通知商户服务器,商户校验后将自己数据库中的订单标记为支付成功
Java PHP C# Python Node.js Android Objective-C

支付宝移动网页收款代码示例:

    BCOrder bcOrder = new BCOrder(渠道code, 金额, 订单编号, 订单标题);//设定订单信息
    bcOrder.setBillTimeout(360);//设置订单超时时间
    bcOrder.setReturnUrl(aliReturnUrl);//设置return url
    try {
        bcOrder = BCPay.startBCPay(bcOrder);
        //out.println(bcOrder.getObjectId());
        out.println(bcOrder.getHtml()); // 输出支付宝收银台到页面
    } catch (BCException e) {
        log.error(e.getMessage(), e);
        out.println(e.getMessage());
    }
    try {
        $data = array(
            'timestamp' => time() * 1000,
            'channel' => 'ALI_WAP', //渠道类型
            'title' => '支付宝移动网页支付测试',   //订单标题
            'bill_no' => "bcdemo" . time(),    //订单编号
            'total_fee' => 1, //订单金额(int 类型) ,单位分
            //use_app非必填参数,boolean型,是否使用APP支付,true使用,否则不使用
            //'use_app' => true;
            'return_url' => 'https://beecloud.cn', //渠道类型:ALI_WEB、ALI_QRCODE、UN_WEB、JD_WAP、JD_WEB时为必填
            'bill_timeout' => 360, //京东(JD*)不支持该参数
        );
        $result = \beecloud\rest\api::bill($data);
        //不使用namespace的用户
        //$result = BCRESTApi::bill($data);
        if(isset($result->url)){
            header("Location:$result->url");
        }else if(isset($result->html)) {
            echo $result->html;
        }
    } catch (Exception $e) {
        echo $e->getMessage();
    }
    BCBill bill = new BCBill('渠道code', '金额', '订单号', '订单标题');

    //支付渠道处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径,中间请勿有#,?等字符,必填参数
    bill.returnUrl = "http://localhost:50003/return_ali_url.aspx";

    //bill.useApp = false;
    try
    {
        BCBill resultBill = BCPay.BCPayByChannel(bill);

        //Response.Write("<span style='color:#00CD00;font-size:20px'>" + resultBill.html + "</span><br/>");
        Response.Redirect(resultBill.url); //跳转到支付宝的收款二维码页面
    }
    catch (Exception excption)
    {
        Response.Write("<span style='color:#00CD00;font-size:20px'>" + excption.Message + "</span><br/>");
    }
                    
    req_params = BCPayReqParams()
    req_params.channel = 'ALI_WAP'
    req_params.title = u'支付测试'
    # 分为单位
    req_params.total_fee = 1
    req_params.bill_no = 'bill number'
    # 支付完成后的跳转页面
    req_params.return_url = 'http://your.return.url.cn/'
    result = bc_pay.pay(req_params)
    # 如果result.result_code为0表示请求成功
    # 然后对返回参数url重定向
                    
    //前端传参
    let data = {}, _this = this;
        data.channel = 'ALI_WAP';//根据不同场景选择不同的支付方式
        data.timestamp = new Date().valueOf();//时间戳,毫秒数
        data.total_fee = 1;//total_fee(int 类型) 单位分
        data.bill_no = `bcdemo${data.timestamp}`;//8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复
        data.title = `node${data.channel}test`;//title UTF8编码格式,32个字节内,最长支持16个汉字
        data.optional = {tag: 'msgtoreturn'};//用户自定义的参数,将会在webhook通知中原样返回,该字段主要用于商户携带订单的自定义数据
        data.bill_timeout = 360;//选填必须为非零正整数,单位为秒,建议最短失效时间间隔必须大于360秒,京东(JD*)不支持该参数。
        data.return_url = "https://beecloud.cn";//当channel参数为 ALI_WEB 或 ALI_QRCODE 或 UN_WEB 或 JD_WAP 或 JD_WEB时为必填
        data.use_app = true;//是否尝试掉起支付宝APP原生支付

    //后端
    const BCRESTAPI = require('beecloud-node-sdk');
    const API = new BCRESTAPI();

    app.post('/api/bill', (req, res, next) => {
        API.bill(req.body).then((response) => {
            res.send(response);
        })
    })
                    

1.2.2.4 附:

支付宝支付必填参数:

参数名 类型 含义 描述 示例
channel String 渠道类型 渠道code ALI_WEB
total_fee Integer 订单总金额 必须是正整数,单位为分 1
bill_no String 商户订单号 8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复 201506101035040000001
title String 订单标题 UTF8编码格式,32个字节内,最长支持16个汉字 白开水
return_url String 同步返回页面 支付渠道处理完请求后,当前页面自动跳转到商户网站里指定页面的http路径,中间请勿有#,?等字符 http://beecloud.cn/returnUrl.jsp

支付宝支付其他可选参数:

参数名 类型 含义 描述 示例
optional Map 附加数据 用户自定义的参数,将会在webhook通知中原样返回,该字段主要用于商户携带订单的自定义数据 {"key1":"value1","key2":"value2",…}
notify_url String 商户自定义回调地址 商户可通过此参数设定回调地址,此地址会覆盖用户在控制台设置的回调地址。必须以 http:// 或 https:// 开头 http://beecloud.cn/notifyUrl.jsp
bill_timeout Integer 订单失效时间 必须为非零正整数,单位为秒,建议最短失效时间间隔必须大于360秒 360
analysis Map 附加数据 商户的用户信息,可用户客户信息分析 {“product”:[{“name”:“product A”, “count”: 2, “price”: 1000}, {“name”: “product B”, “count”:1, “price”: 2000}], “ip”:“111.121.1.10”}
product A,B是产品名字,2是件数,1000是单价(分),ip是客户端客户的ip

1.2.3 网页上实现微信收款

1.2.3.1 微信公众号内网页收款

  1. 微信公众号配置参数:文档
  2. 用户发起付款请求
  3. 系统生成付款订单,包括订单号,订单标题,金额等信息
  4. 将订单存入自己系统数据库中,标记订单为未支付
  5. 调用BeeCloud SDK中的支付接口,请求微信
  6. 返回必要的参数,然后将这些参数传入到微信的js方法中
  7. 跳转到微信APP付款
  8. 支付完成返回微信公众号页面
  9. 支付成功,webhook通知商户服务器,商户校验后将自己数据库中的订单标记为支付成功
Java PHP C# Python Node.js Android Objective-C

微信公众号内网页收款代码示例:

    //后端部分
    //微信 公众号id(读取配置文件conf.properties)及微信 redirec_uri
    Properties prop = loadProperty();
    String wxJSAPIAppId = prop.get("wxJSAPIAppId").toString();
    String wxJSAPISecret = prop.get("wxJSAPISecret").toString();
    String wxJSAPIRedirectUrl = "http://javademo.beecloud.cn/demo/pay_example/pay.jsp?paytype=" + channel;
    String encodedWSJSAPIRedirectUrl = URLEncoder.encode(wxJSAPIRedirectUrl);
    if (request.getParameter("code") == null || request.getParameter("code").toString().equals("")) {
        String redirectUrl = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + wxJSAPIAppId + "&redirect_uri=" + encodedWSJSAPIRedirectUrl + "&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect";
        log.info("wx jsapi redirct url:" + redirectUrl);
        response.sendRedirect(redirectUrl);
    } else {
        String code = request.getParameter("code");
        String result = sendGet("https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + wxJSAPIAppId + "&secret=" + wxJSAPISecret + "&code=" + code + "&grant_type=authorization_code");
        log.info("result:" + result);
        JSONObject resultObject = JSONObject.fromObject(result);
        if (resultObject.containsKey("errcode")) {
            out.println("获取access_token出错!错误信息为:" + resultObject.get("errmsg").toString());
        } else {
            String openId = resultObject.get("openid").toString();
            bcOrder.setOpenId(openId);
            try {
                bcOrder = BCPay.startBCPay(bcOrder);
                out.println(bcOrder.getObjectId());
                System.out.print(bcOrder.getObjectId());
                Map<String, String> map = bcOrder.getWxJSAPIMap();
                jsapiAppid = map.get("appId").toString();
                timeStamp = map.get("timeStamp").toString();
                nonceStr = map.get("nonceStr").toString();
                jsapipackage = map.get("package").toString();
                signType = map.get("signType").toString();
                paySign = map.get("paySign").toString();
            } catch (BCException e) {
                log.error(e.getMessage(), e);
                out.println(e.getMessage());
            }
        }
    }

    //js部分
    <script type="text/javascript">
        callpay();
        function jsApiCall() {
            var data = {
                //以下参数的值由BCPayByChannel方法返回来的数据填入即可
                "appId": "<%=jsapiAppid%>",
                "timeStamp": "<%=timeStamp%>",
                "nonceStr": "<%=nonceStr%>",
                "package": "<%=jsapipackage%>",
                "signType": "<%=signType%>",
                "paySign": "<%=paySign%>"
            };
            alert(JSON.stringify(data));
            WeixinJSBridge.invoke(
                    'getBrandWCPayRequest',
                    data,
                    function (res) {
                        alert(res.err_msg);
                        alert(JSON.stringify(res));
                        WeixinJSBridge.log(res.err_msg);
                    }
            );
        }
        function callpay() {
            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>
                    
    /**
     * 微信用户的openid获取请参考官方demo sdk和文档
     * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
     * 微信获取openid php代码, 运行环境是微信内置浏览器访问时
     *
     * 注意:
     *      请修改lib/WxPayPubHelper/WxPay.pub.config.php配置文件中的参数:
     *      1.APPID, APPSECRET请修改为商户自己的微信参数(MCHID, KEY在beecloud平台创建的应用中配置);
     *      2.JS_API_CALL_URL针对当前的demo,应该是http(s)://<your domain>/<your path>/pay.bill.php?type=WX_JSAPI,可根据具体情况进行配置调整;
    *      3.请检查方法createOauthUrlForCode是否对回调链接地址(redirect_uri)进行urlencode处理,如果没有请自行添加
    *      3.特别要强调的是JS_API_CALL_URL的访问域名必须与微信公众平台配置的授权回调页面域名一致.
    */
    //获取openid
    header("Content-type: text/html; charset=utf-8");
    include_once('lib/WxPayPubHelper/WxPayPubHelper.php');
    $jsApi = new JsApi_pub();
    //网页授权获取用户openid
    //通过code获得openid
    if (!isset($_GET['code'])){
        //触发微信返回code码
        $url = $jsApi->createOauthUrlForCode(WxPayConf_pub::JS_API_CALL_URL);
        header("Location: $url");
    } else {
        //获取code码,以获取openid
        $code = $_GET['code'];
        $jsApi->setCode($code);
        $openid = $jsApi->getOpenId();
    }

    //获取微信支付相关参数
    try {
        $data = array(
            'timestamp' => time() * 1000,
            'channel' => 'WX_JSAPI', //渠道类型,
            'openid' => $openid,
            'title' => '微信移动网页支付测试',   //订单标题
            'bill_no' => "bcdemo" . time(),    //订单编号
            'total_fee' => 1 //订单金额(int 类型) ,单位分
        );
        $result = \beecloud\rest\api::bill($data);
        //不使用namespace的用户
        //$result = BCRESTApi::bill($data);
        if ($result->result_code != 0) {
            print_r($result);
            exit();
        }
        $jsApiParam = array(
            "appId" => $result->app_id,
            "timeStamp" => $result->timestamp,
            "nonceStr" => $result->nonce_str,
            "package" => $result->package,
            "signType" => $result->sign_type,
            "paySign" => $result->pay_sign
        );
    } catch (Exception $e) {
        die($e->getMessage());
    }

    //页面js部分
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>BeeCloud微信安全支付</title>
    </head>
    <script type="text/javascript">
        //调用微信JS api 支付
        function jsApiCall() {
            WeixinJSBridge.invoke(
                    'getBrandWCPayRequest',
                    <?php echo json_encode($jsApiParam);?>,
                function(res){
                    /* 参考:https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=7_7&index=6
                     * res.err_msg的返回值
                     * 1.支付成功, get_brand_wcpay_request:ok
                     * 2.支付过程中用户取消, get_brand_wcpay_request:cancel
                     * 3.支付失败, get_brand_wcpay_request:fail
                     */
                    alert(JSON.stringify(res)) //供调试使用
                    if(res.err_msg == "get_brand_wcpay_request:ok" ) {
                    //用户自己的操作, eg: window.location.href = '用户自己的URL';
                    }else{
                        //用户自己的操作, eg: window.location.href = '用户自己的URL';
                    }
                }
            );
        }
        function callpay() {
            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>
    <body onload="callpay();"> </body>
    </html>
                    
    //服务端部分,服务端将从beecloud获取的参数传递给js,去调用微信的方法实现支付
    BCBill bill = new BCBill('渠道code', '金额', '订单号', '订单标题');
    bill.openId = jsApiPay.openid;
    try
    {
        BCBill resultBill = BCPay.BCPayByChannel(bill);
        timeStamp = resultBill.timestamp;
        noncestr = resultBill.noncestr;
        package = resultBill.package;
        paySign = resultBill.paySign;
        signType = resultBill.signType;
    }
    catch (Exception excption)
    {
        Response.Write("<span style='color:#00CD00;font-size:20px'>" + excption.Message + "</span><br/>");
    }


    //页面js部分
    <div style="text-align:center;">
        <button onclick="callpay()" style="width:400px; height:300px; font-size:36px" >付款</button>
    </div>

    <script type="text/javascript">
        //下面的两个js方法是用来调用jsapi的
        function onBridgeReady() {
            var data = {
                //以下参数的值由BCPayByChannel方法返回来的数据填入即可
                "appId": "<%=appid%>",
                "timeStamp": "<%=timeStamp%>",
                "nonceStr": "<%=noncestr%>",
                "package": "<%=package%>",
                "signType": "<%=signType%>",
                "paySign": "<%=paySign%>"
            };
            alert(JSON.stringify(data));
            WeixinJSBridge.invoke(
                    'getBrandWCPayRequest',
                    data,
                    function (res) {
                        alert(res.err_msg);
                        alert(JSON.stringify(res));
                        if (res.err_msg == "get_brand_wcpay_request:ok") {
                            //
                        }
                        // 使用以上方式判断前端返回
                        //微信团队郑重提示:res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
                    }
            );
        }
        function callpay() {
            if (typeof WeixinJSBridge == "undefined") {
                if (document.addEventListener) {
                    document.addEventListener('WeixinJSBridgeReady', onBridgeReady, false);
                } else if (document.attachEvent) {
                    document.attachEvent('WeixinJSBridgeReady', onBridgeReady);
                    document.attachEvent('onWeixinJSBridgeReady', onBridgeReady);
                }
            } else {
                onBridgeReady();
            }
        }
    </script>
                    
    # 先获取open id
    req_params = BCPayReqParams()
    req_params.channel = 'WX_JSAPI'    # 或者BC_WX_JSAPI
    req_params.title = u'支付测试'
    # 分为单位
    req_params.total_fee = 1
    req_params.bill_no = 'bill number'
    req_params.openid = open_id
    result = bc_pay.pay(req_params)
    # 如果result.result_code为0表示请求成功
    # 然后对返回参数(包含app_id, package, nonce_str, timestamp, pay_sign, sign_type)做下一步处理
                    
    /**
     * 微信用户的openid获取请参考官方demo sdk和文档
     * https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=11_1
     * 微信获取openid php代码, 运行环境是微信内置浏览器访问时
     */
    /前端传参
    let data = {}, _this = this;
        data.channel = 'WX_JSAPI';//根据不同场景选择不同的支付方式
        data.timestamp = new Date().valueOf();//时间戳,毫秒数
        data.total_fee = 1;//total_fee(int 类型) 单位分
        data.bill_no = `bcdemo${data.timestamp}`;//8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复
        data.title = `node${data.channel}test`;//title UTF8编码格式,32个字节内,最长支持16个汉字
        data.optional = {tag: 'msgtoreturn'};//用户自定义的参数,将会在webhook通知中原样返回,该字段主要用于商户携带订单的自定义数据
        data.bill_timeout = 360;//选填必须为非零正整数,单位为秒,建议最短失效时间间隔必须大于360秒,京东(JD*)不支持该参数。
        data.openid = '0950c062-5e41-xxxxxxxxxxx';//openid

    //后端
    const BCRESTAPI = require('beecloud-node-sdk');
    const API = new BCRESTAPI();

    app.post('/api/bill', (req, res, next) => { //支付
        API.bill(req.body).then((response) => {
            res.send(response);
        })
    })
                    

1.2.3.2 微信移动网页(非微信浏览器)收款

  1. 用户发起付款请求
  2. 系统生成付款订单,包括订单号,订单标题,金额等信息
  3. 将订单存入自己系统数据库中,标记订单为未支付
  4. 调用BeeCloud SDK中的支付接口,请求微信
  5. 微信返回一个url或者html
  6. 通过跳转到url或者将html输出到页面进而打开微信的跳转中转页页面,打开微信APP实现收款
  7. 支付完成,用户跳转到设置的return url地址
  8. 支付成功,webhook通知商户服务器,商户校验后将自己数据库中的订单标记为支付成功
Java PHP C# Python Node.js Android Objective-C

微信移动网页(非微信浏览器)收款代码示例:

    BCOrder bcOrder = new BCOrder(渠道code, 金额, 订单编号, 订单标题);//设定订单信息
    bcOrder.setReturnUrl(returnUrl);
    try {
        bcOrder = BCPay.startBCPay(bcOrder);
        response.sendRedirect(bcOrder.getUrl()); //跳转到微信APP
    } catch (BCException e) {
        log.error(e.getMessage(), e);
        out.println(e.getMessage());
    }
                    
    try {
        $data = array(
            'timestamp' => time() * 1000,
            'channel' => 'BC_WX_WAP', //渠道类型
            'title' => '微信移动网页(非微信浏览器)测试',   //订单标题
            'bill_no' => "bcdemo" . time(),    //订单编号
            'total_fee' => 1 //订单金额(int 类型) ,单位分
        );
        $result = \beecloud\rest\api::bill($data);
        //不使用namespace的用户
        //$result = BCRESTApi::bill($data);
        if(isset($result->url)){
            header("Location:$result->url");
        }else if(isset($result->html)) {
            echo $result->html;
        }
    } catch (Exception $e) {
        echo $e->getMessage();
    }
                    
    BCBill bill = new BCBill('渠道code', '金额', '订单号', '订单标题');
    bill.returnUrl = "http://www.baidu.com";
    try
    {
        BCBill resultBill = BCPay.BCPayByChannel(bill);
        //Response.Write("<span style='color:#00CD00;font-size:20px'>" + resultBill.html + "</span><br/>");
        Response.Redirect(resultBill.url); //跳转到微信的中转页
    }
    catch (Exception excption)
    {
        Response.Write("<span style='color:#00CD00;font-size:20px'>" + excption.Message + "</span><br/>");
    }
                    
    req_params = BCPayReqParams()
    req_params.channel = 'BC_WX_WAP'
    req_params.title = u'支付测试'
    # 分为单位
    req_params.total_fee = 1
    req_params.bill_no = 'bill number'
    # 支付完成后的跳转页面
    req_params.return_url = 'http://your.return.url.cn/'
    result = bc_pay.pay(req_params)
    # 如果result.result_code为0表示请求成功
    # 然后对返回参数url重定向
                    
    //前端传参
    let data = {}, _this = this;
        data.channel = 'BC_WX_WAP';//根据不同场景选择不同的支付方式
        data.timestamp = new Date().valueOf();//时间戳,毫秒数
        data.total_fee = 1;//total_fee(int 类型) 单位分
        data.bill_no = `bcdemo${data.timestamp}`;//8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复
        data.title = `node${data.channel}test`;//title UTF8编码格式,32个字节内,最长支持16个汉字
        data.optional = {tag: 'msgtoreturn'};//用户自定义的参数,将会在webhook通知中原样返回,该字段主要用于商户携带订单的自定义数据
        data.bill_timeout = 360;//选填必须为非零正整数,单位为秒,建议最短失效时间间隔必须大于360秒,京东(JD*)不支持该参数。

    //后端
    const BCRESTAPI = require('beecloud-node-sdk');
    const API = new BCRESTAPI();

    app.post('/api/bill', (req, res, next) => {
        API.bill(req.body).then((response) => {
            res.send(response);
        })
    })
                    

1.2.3.3 微信在PC网页通过二维码收款

  1. 用户发起付款请求
  2. 系统生成付款订单,包括订单号,订单标题,金额等信息
  3. 将订单存入自己系统数据库中,标记订单为未支付
  4. 调用BeeCloud SDK中的支付接口,请求微信
  5. 微信返回收款二维码的值
  6. 通过代码生成二维码展示到商家自己的页面上,用户扫码付款
  7. 支付完成,没有return_url可以使用
  8. 支付成功,webhook通知商户服务器,商户校验后将自己数据库中的订单标记为支付成功
Java PHP C# Python Node.js Android Objective-C

微信在PC网页通过二维码收款代码示例:

    BCOrder bcOrder = new BCOrder(渠道code, 金额, 订单编号, 订单标题);//设定订单信息
    try {
        bcOrder.setNotifyUrl("https:///apidynamic.beecloud.cn/test");
        bcOrder = BCPay.startBCPay(bcOrder);
        //将bcOrder.getCodeUrl()是二维码的值,用生成二维码的方法生成二维码即可
    } catch (BCException e) {
        log.error(e.getMessage(), e);
        out.println(e.getMessage());
    }
                    
    //获取二维码地址
    try {
        $data = array(
            'timestamp' => time() * 1000,
            'channel' => 'WX_NATIVE', //渠道类型
            'title' => '微信扫码测试',   //订单标题
            'bill_no' => "bcdemo" . time(),    //订单编号
            'total_fee' => 1 //订单金额(int 类型) ,单位分
        );
        $result = \beecloud\rest\api::bill($data);
        //不使用namespace的用户
        //$result = BCRESTApi::bill($data);
        if ($result->result_code != 0) {
            print_r($result);
            exit();
        }
        $code_url = $result->code_url;
    } catch (Exception $e) {
        echo $e->getMessage();
    }

    //页面js部分
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>BeeCloud微信扫码示例</title>
    </head>
    <body>
    <div align="center" id="qrcode" ></div>
    </body>
    <script src="statics/jquery-1.11.1.min.js"></script>
    <script src="statics/qrcode.js"></script>
    <script>
        if(<?php echo $code_url != NULL; ?>) {
            var options = {text: "<?php echo $code_url;?>"};
            //参数1表示图像大小,取值范围1-10;参数2表示质量,取值范围'L','M','Q','H'
            var canvas = BCUtil.createQrCode(options);
            var wording=document.createElement('p');
            wording.innerHTML = "扫我 扫我";
            var element=document.getElementById("qrcode");
            element.appendChild(wording);
            element.appendChild(canvas);
        }
    </script>
    </body>
    </html>
                    
    BCBill bill = new BCBill('渠道code', '金额', '订单号', '订单标题');
    try
    {
        BCBill resultBill = BCPay.BCPayByChannel(bill);
        string str = resultBill.codeURL;

        //初始化二维码生成工具
        QRCodeEncoder qrCodeEncoder = new QRCodeEncoder();
        qrCodeEncoder.QRCodeEncodeMode = QRCodeEncoder.ENCODE_MODE.BYTE;
        qrCodeEncoder.QRCodeErrorCorrect = QRCodeEncoder.ERROR_CORRECTION.M;
        qrCodeEncoder.QRCodeVersion = 0;
        qrCodeEncoder.QRCodeScale = 4;

        //将字符串生成二维码图片
        Bitmap image = qrCodeEncoder.Encode(str, Encoding.Default);
        //保存为PNG到内存流
        MemoryStream ms = new MemoryStream();
        image.Save(ms, ImageFormat.Png);

        //输出二维码图片
        Response.BinaryWrite(ms.GetBuffer());
        Response.ContentType = "image/Png";
    }
    catch (Exception excption)
    {
        Response.Write("<span style='color:#00CD00;font-size:20px'>" + excption.Message + "</span><br/>");
    }
                    
    req_params = BCPayReqParams()
    req_params.channel = 'WX_NATIVE'  # 或者BC_NATIVE
    req_params.title = u'支付测试'
    # 分为单位
    req_params.total_fee = 1
    req_params.bill_no = 'bill number'
    result = bc_pay.pay(req_params)
    # 如果result.result_code为0表示请求成功
    # 然后根据返回参数code_url生成二维码
                    
    //前端传参
    let data = {}, _this = this;
        data.channel = 'WX_NATIVE';//根据不同场景选择不同的支付方式
        data.timestamp = new Date().valueOf();//时间戳,毫秒数
        data.total_fee = 1;//total_fee(int 类型) 单位分
        data.bill_no = `bcdemo${data.timestamp}`;//8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复
        data.title = `node${data.channel}test`;//title UTF8编码格式,32个字节内,最长支持16个汉字
        data.optional = {tag: 'msgtoreturn'};//用户自定义的参数,将会在webhook通知中原样返回,该字段主要用于商户携带订单的自定义数据
        data.bill_timeout = 360;//选填必须为非零正整数,单位为秒,建议最短失效时间间隔必须大于360秒,京东(JD*)不支持该参数。

    //后端
    const BCRESTAPI = require('beecloud-node-sdk');
    const API = new BCRESTAPI();

    app.post('/api/bill', (req, res, next) => {
        API.bill(req.body).then((response) => {
            res.send(response);
        })
    })
                    

微信支付必填参数:

参数名 类型 含义 描述 示例
channel String 渠道类型 渠道code WX_NATIVE
total_fee Integer 订单总金额 必须是正整数,单位为分 1
bill_no String 商户订单号 8到32位数字和/或字母组合,请自行确保在商户系统中唯一,同一订单号不可重复提交,否则会造成订单重复 201506101035040000001
title String 订单标题 UTF8编码格式,32个字节内,最长支持16个汉字