|
| 1 | +# omnipay-99bill |
| 2 | + |
| 3 | +基于Omnipay的快钱支付SDK |
| 4 | + |
| 5 | +该文档共包含以下5个部分: |
| 6 | +1、创建交易 |
| 7 | +2、支付回调 |
| 8 | +3、交易查询 |
| 9 | +4、网关退款 |
| 10 | + |
| 11 | +## Quick Start 快速开始 |
| 12 | + |
| 13 | +依赖于[Omnipay](https://github.com/omnipay/omnipay) |
| 14 | + |
| 15 | +PHP版本要求:PHP5.6+ |
| 16 | + |
| 17 | + |
| 18 | +### Install 安装 |
| 19 | + |
| 20 | +通过 [Composer](http://getcomposer.org/) 安装,可以运行: |
| 21 | + |
| 22 | +```shell |
| 23 | + |
| 24 | +$ composer require laraveler/omnipay-99bill -vvv |
| 25 | + |
| 26 | +``` |
| 27 | + |
| 28 | +> 注意: |
| 29 | +> 关于商户号:快钱商家帐号需要联系快钱开通之后才能获取,如果商户号为10012138842,在项目中使用的商户号格式为"快钱商户号01",如1001213884201,退款接口除外,需要的是不带01的格式。 |
| 30 | +> 关于密钥:自行根据快钱文档生成公钥和私钥,其中公钥上传到快钱,然后再从快钱下载官方秘钥放到项目当中,自己生成的私钥则用于创建支付时加密使用。 |
| 31 | +> 关于支付验证:支付成功后的同步回调和异步回调均为Get方式,需要对回调的参数进行验证,以确保是快钱官方的回调。 |
| 32 | +> 关于订单查询:订单交易状态查询接口除了商户号之外,还需要一个查询key,需要联系快钱的销售人员开通该功能,并获取对应的查询key. |
| 33 | +> 关于退款:网关退款接口除了商户号之外,还需要一个退款key,需要联系快钱的销售人员开通该功能,并获取对应的退款key. |
| 34 | +
|
| 35 | + |
| 36 | +### 开启沙盒调试模式 |
| 37 | + |
| 38 | +> 调试过程可以用如下代码开启沙盒环境,正式生产环境请去掉此代码。 |
| 39 | +
|
| 40 | +```php |
| 41 | +$gateway->setTestMode(true); |
| 42 | +``` |
| 43 | + |
| 44 | +### 创建交易 |
| 45 | + |
| 46 | +> 业务字段说明 |
| 47 | +
|
| 48 | +|字段名|是否必传 |说明| |
| 49 | +|:----- |:-----|-----| |
| 50 | +|orderId|Yes |商户订单号,商户可以根据自己订单号的定义规则来定义该值| |
| 51 | +|orderAmount|Yes |订单金额,金额以“分”为单位,商户测试以1分测试即可,切勿以大金额测试。| |
| 52 | +|payerName|No |支付人姓名| |
| 53 | +|payerContactType|No |支付人联系类型,1 代表电子邮件方式;2 代表手机联系方式| |
| 54 | +|payerContact|No |支付人联系方式,与payerContactType设置对应,payerContactType为1,则填写邮箱地址;payerContactType为2,则填写手机号码| |
| 55 | +|productId|No |商品代码| |
| 56 | +|productName|No |商品名称| |
| 57 | +|productNum|No |商品数量| |
| 58 | +|productDesc|No |商品描述| |
| 59 | +|ext1|No |扩展字段1,商户可以传递自己需要的参数,支付完快钱会原值返回| |
| 60 | +|ext2|No |扩展字段2,商户可以传递自己需要的参数,支付完快钱会原值返回| |
| 61 | + |
| 62 | +> 网站端 - 发起支付代码 |
| 63 | +
|
| 64 | +```php |
| 65 | +$gateway = \Omnipay\Omnipay::create('Bill99'); |
| 66 | +$gateway->setMchId('mch-id'); //商户号 |
| 67 | +$gateway->setPrivateKey('private_key'); //私钥内容,可以是文件路径,也可以是内容,如果是内容,保持全在同一行。 |
| 68 | +$gateway->setReturnUrl('https://www.example.com/return');//支付成功后同步跳转的url |
| 69 | +$gateway->setNotifyUrl('https://www.example.com/notify');//支付成功后异步通知url |
| 70 | + |
| 71 | +$request = $gateway->purchase([ |
| 72 | + 'orderId' => date('YmdHis') . mt_rand(1000, 9999), |
| 73 | + 'orderAmount' => 1, |
| 74 | +]); |
| 75 | + |
| 76 | +$response = $request->send(); |
| 77 | +$response->redirect(); |
| 78 | +exit; |
| 79 | +``` |
| 80 | + |
| 81 | +> 移动端 - 发起支付代码 |
| 82 | +
|
| 83 | +```php |
| 84 | +$gateway = \Omnipay\Omnipay::create('Bill99'); |
| 85 | +$gateway->setMchId('mch-id'); //商户号 |
| 86 | +$gateway->setPrivateKey('private_key'); //私钥内容,可以是文件路径,也可以是内容,如果是内容,保持全在同一行。 |
| 87 | +$gateway->setReturnUrl('https://www.example.com/return');//支付成功后同步跳转的url |
| 88 | +$gateway->setNotifyUrl('https://www.example.com/notify');//支付成功后异步通知url |
| 89 | + |
| 90 | +$request = $gateway->wapPurchase([ |
| 91 | + 'orderId' => date('YmdHis') . mt_rand(1000, 9999), |
| 92 | + 'orderAmount' => 1, |
| 93 | +]); |
| 94 | + |
| 95 | +$response = $request->send(); |
| 96 | +$response->redirect(); |
| 97 | +exit; |
| 98 | +``` |
| 99 | + |
| 100 | +### 支付回调 |
| 101 | + |
| 102 | +> 回调成功的业务参数 |
| 103 | +
|
| 104 | +|字段名|说明| |
| 105 | +|:----- |-----| |
| 106 | +|orderId|商户订单号 | |
| 107 | +|orderAmount|订单金额,金额以“分”为单位| |
| 108 | +|orderTime|订单交易创建时间 | |
| 109 | +|dealId|快钱交易号 | |
| 110 | +|dealTime|交易成功时间 | |
| 111 | +|payAmount|实际交易金额,金额以“分”为单位 | |
| 112 | +|bankDealId|银行交易号 | |
| 113 | +|bankId|银行简码 | |
| 114 | +|fee|手续费 | |
| 115 | +|bindMobile|绑定的手机号 | |
| 116 | +|bindCard|绑定的卡号 | |
| 117 | +|payType|支付方式,详见快钱官方文档说明 | |
| 118 | +|ext1|扩展字段1 | |
| 119 | +|ext2|扩展字段2 | |
| 120 | + |
| 121 | +> 说明:把自己的公钥上传到快钱之后,从快钱下载下来的密钥文件名类似"99bill[1].cert.rsa.20140803.cer"格式。 |
| 122 | +
|
| 123 | +> 回调验证代码(快钱回调方式为Get) |
| 124 | +
|
| 125 | +```php |
| 126 | +$gateway = Omnipay::create('Bill99'); |
| 127 | +$gateway->setMchId('mch-id'); //商户号 |
| 128 | +$gateway->setPublicKey('99bill_publickey'); //快钱下载的密钥内容,可以是文件路径,也可以是内容,如果是内容,保持全在同一行。 |
| 129 | +$request = $gateway->completePurchase(); |
| 130 | +$request->setParams(array_merge($_GET));//获取参数的方法可以用$_GET,也可以用某些框架自带的获取方法,总之要传入url中的Get参数 |
| 131 | + |
| 132 | +try { |
| 133 | + $response = $request->send(); |
| 134 | + if ($response->isPaid()) { |
| 135 | + $data = $response->getData();//业务参数 |
| 136 | + |
| 137 | + // @todo 支付成功业务逻辑处理,根据返回的业务参数,修改数据库中对应的订单状态 |
| 138 | + |
| 139 | + /** 这里需要注意,如果同步回调和同步回调(两者均为GET)在同一处处理, |
| 140 | + * 需要通过一定方式区分是异步还是同步,两者返回信息不同,如用户登录状态 |
| 141 | + */ |
| 142 | + |
| 143 | + //异步回调值,该返回值为快钱必需 |
| 144 | + die($response->asyncResult(true,$redirectUrl)); //成功第一个参数为true,第二个参数为要跳转的url |
| 145 | + //同步回调 |
| 146 | + // redirect跳转页面... |
| 147 | + } else { |
| 148 | + // @todo 支付失败的业务逻辑 |
| 149 | + //异步回调值,该返回值为快钱必需 |
| 150 | + die($response->asyncResult(false)); //失败只需要传入false |
| 151 | + } |
| 152 | +} catch (Exception $e) { |
| 153 | + // @todo 这里为支付异常业务逻辑 |
| 154 | + //异步回调值,该返回值为快钱必需 |
| 155 | + die($response->asyncResult(false)); //失败只需要传入false |
| 156 | +} |
| 157 | +``` |
| 158 | + |
| 159 | +### 查询交易支付状态 |
| 160 | + |
| 161 | +> 如果因快钱故障或商户自己服务器故障,成功的交易导致回调失败,则可以用该方法进行查单,通过查单的结果进行数据库状态变更。 |
| 162 | +
|
| 163 | +> 查询请求业务参数组合一 |
| 164 | +
|
| 165 | +|字段名|是否必传 |说明| |
| 166 | +|:----- |:-----|-----| |
| 167 | +|orderId|Yes |商户订单号| |
| 168 | +|queryType|No |查询方式默认为2,即根据商户订单号查询| |
| 169 | +|requestPage|No |在查询结果数据总量很大时,快钱会将支付结果分多次返回。本参数表示商户需要得到的记录集页码。默认为1,表示第1 页| |
| 170 | + |
| 171 | +> 查询请求业务参数组合二 |
| 172 | +
|
| 173 | +|字段名|是否必传 |说明| |
| 174 | +|:----- |:-----|-----| |
| 175 | +|queryType|Yes |值固定为1,即根据日期查询| |
| 176 | +|startTime|Yes |开始时间,数字串,一共14 位,格式为:年[4 位]月[2 位]日[2 位]时[2 位]分[2 位]秒[2位],例如:20071117020101| |
| 177 | +|endTime|Yes |结束时间,数字串,一共14 位,格式为:年[4 位]月[2 位]日[2 位]时[2 位]分[2 位]秒[2位],例如:20071117020101| |
| 178 | +|requestPage|No |在查询结果数据总量很大时,快钱会将支付结果分多次返回。本参数表示商户需要得到的记录集页码。默认为1,表示第1 页| |
| 179 | + |
| 180 | +> 交易查询 - 实现代码 |
| 181 | +```php |
| 182 | + |
| 183 | +$gateway = \Omnipay\Omnipay::create('Bill99'); |
| 184 | +$gateway->setMchId('mch-id'); //商户号 |
| 185 | +$gateway->setQueryKey('query_key');//交易查询key |
| 186 | + |
| 187 | +//查询方式一 |
| 188 | +$request = $gateway->query([ |
| 189 | + 'orderId' => '201805261456145505', |
| 190 | +]); |
| 191 | + |
| 192 | +//查询方式二 |
| 193 | +/* |
| 194 | +$request = $gateway->query([ |
| 195 | + 'queryType' => 1, |
| 196 | + 'startTime' => '20180501000101', |
| 197 | + 'endTime' => '20180527000101', |
| 198 | +]); |
| 199 | +*/ |
| 200 | + |
| 201 | +try { |
| 202 | + $response = $request->send(); |
| 203 | + if ($response->isSuccessful()) { |
| 204 | + $data=$response->getData(); |
| 205 | + //@todo 支付成功业务逻辑处理,根据返回的业务参数,修改数据库中对应的订单状态 |
| 206 | + }else{ |
| 207 | + // @todo 这里为支付异常业务逻辑 |
| 208 | + } |
| 209 | +} catch (Exception $e) { |
| 210 | + // @todo 这里为支付异常业务逻辑 |
| 211 | +} |
| 212 | + |
| 213 | +``` |
| 214 | + |
| 215 | +### 订单网关退款 |
| 216 | + |
| 217 | +> 如未开通网关退款,则需要登录快钱官方商家后台进行退款操作,开通网关退款之后,则可以直接调用此接口退款。 |
| 218 | +
|
| 219 | +> 警告:此接口为无密退款,因此开发人员需要绝对保证操作后台安全,或加强退款安全验证机制,否则因安全系数太低导致的事故请自行承担。 |
| 220 | +
|
| 221 | +> 注意一:这里的商户号为不加01的商户号!!! |
| 222 | +
|
| 223 | +> 注意二:这里面的退款金额以人民币元为单位!!! |
| 224 | +
|
| 225 | +> 注意三:同一笔交易可以分多次退款,但是退款总金额不得超过订单支付总金额 |
| 226 | +
|
| 227 | +> 退款请求业务参数 |
| 228 | +
|
| 229 | +|字段名|是否必传 |说明| |
| 230 | +|:----- |:-----|-----| |
| 231 | +|orderId|Yes |商户订单号| |
| 232 | +|txOrder|Yes |退款流水号,长度不超过50,英文和数字组成| |
| 233 | +|amount|Yes |退款金额,整数或小数位为两位,以人民币元为单位。| |
| 234 | +|postdate|Yes |退款提交时间,数字串,一共14 位,格式为:年[4 位]月[2 位]日[2 位]时[2 位]分[2 位]秒[2位],例如:20071117020101| |
| 235 | + |
| 236 | +> 退款成功业务参数 |
| 237 | +
|
| 238 | +|字段名|说明| |
| 239 | +|:----- |-----| |
| 240 | +|orderId|商户订单号 | |
| 241 | +|txOrder|退款流水号| |
| 242 | +|amount|退款金额| |
| 243 | + |
| 244 | +> 网关退款 - 实现代码 |
| 245 | +```php |
| 246 | +$gateway = \Omnipay\Omnipay::create('Bill99'); |
| 247 | +$gateway->setMchId('mch-id'); //商户号 |
| 248 | +$gateway->setRefundKey('refund_key');//退款key |
| 249 | + |
| 250 | +$request = $gateway->refund([ |
| 251 | + 'orderId' => 'P270000180502933093', |
| 252 | + 'txOrder' => date('YmdHis'), |
| 253 | + 'amount' => 0.01, |
| 254 | + 'postdate' => date('YmdHis'), |
| 255 | +]); |
| 256 | + |
| 257 | +try { |
| 258 | + $response = $request->send(); |
| 259 | + if ($response->isSuccessful()) { |
| 260 | + $data=$response->getData(); |
| 261 | + // @todo 退款成功业务逻辑处理,根据返回的业务参数,修改数据库中对应的订单状态 |
| 262 | + }else{ |
| 263 | + // @todo 这里为退款异常业务逻辑 |
| 264 | + } |
| 265 | +} catch (Exception $e) { |
| 266 | + // @todo 这里为退款异常业务逻辑 |
| 267 | +} |
| 268 | +``` |
0 commit comments