├── .gitignore ├── README.md ├── example ├── backOrderQueryTest.py ├── backOrderTest.py ├── queryOrderTest.py ├── refundTest.py └── tradeTest.py └── ipaynowPythonSdk ├── ipaynow ├── __init__.py ├── error.py ├── interface.py ├── jsonParseFaced.py ├── md5Faced.py ├── packMsg.py ├── paramlist.py ├── queryOrder.py ├── refund.py ├── trade.py ├── unpackMsg.py ├── utils.py └── version.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | \.idea/ 3 | 4 | ipaynowPythonSdk/ipaynow\.egg-info/ 5 | 6 | ipaynowPythonSdk/dist/ 7 | 8 | ipaynowPythonSdk/build/ 9 | 10 | ipaynowPythonSdk/ipaynow/__pycache__/ 11 | 12 | ipaynow_pay_python\.rar 13 | 14 | .idea 15 | example/__pycache__/ 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # 聚合支付SDK使用说明 # 3 | 4 | ## 版本变更记录 ## 5 | 6 | - 1.0.0 : 初稿 7 | - 1.0.1 :接口按渠道分开,增加微信支付宝外的渠道方法 8 | 9 | ## 目录 ## 10 | 11 | [1. 概述](#1) 12 | 13 |     [1.1 简介](#1.1) 14 | 15 |     [1.2 如何获取](#1.2) 16 | 17 |     [1.3 使用说明](#1.3) 18 | 19 | [2. API](#2) 20 | 21 |     [2.1 聚合交易API](#2.1) 22 | 23 |         [微信被扫支付](#2.1.1) 24 | 25 |         [支付宝被扫支付](#2.1.2) 26 | 27 |         [手Q被扫支付](#2.1.3) 28 | 29 |         [京东被扫支付](#2.1.4) 30 | 31 |         [银联被扫支付](#2.1.5) 32 | 33 |         [微信主扫支付](#2.1.6) 34 | 35 |         [支付宝主扫支付](#2.1.7) 36 | 37 |         [手Q主扫支付](#2.1.8) 38 | 39 |         [京东主扫支付](#2.1.9) 40 | 41 |         [银联主扫支付](#2.1.10) 42 | 43 |         [微信公众号支付](#2.1.11) 44 | 45 |         [支付宝公众号支付](#2.1.13) 46 | 47 |         [手Q公众号支付](#2.1.15) 48 | 49 |         [微信H5](#2.1.17) 50 | 51 |         [支付宝H5](#2.1.18) 52 | 53 |         [银联H5](#2.1.19) 54 | 55 |         [招行一网通H5](#2.1.20) 56 | 57 |         [手Q H5](#2.1.21) 58 | 59 |         [支付宝网页web](#2.1.22) 60 | 61 |         [银联网页web](#2.1.23) 62 | 63 |         [微信小程序支付](#2.1.24) 64 | 65 |     [2.2 支付结果通知](#2.2) 66 | 67 |     [2.3 订单查询API](#2.3) 68 | 69 |         [用户主扫支付订单查询](#2.3.1) 70 | 71 |         [用户被扫支付订单查询](#2.3.2) 72 | 73 |         [商户公众号支付订单查询](#2.3.3) 74 | 75 |         [商户H5支付订单查询](#2.3.4) 76 | 77 |         [商户网页支付订单查询](#2.3.5) 78 | 79 |         [商户微信App支付订单查询](#2.3.6) 80 | 81 |     [2.4 退款API](#2.4) 82 | 83 |         [退款](#2.4.1) 84 | 85 |         [退款查询](#2.4.2) 86 | 87 |         [撤销](#2.4.3) 88 | 89 |         [撤销查询](#2.4.4) 90 | 91 | 92 |

1. 概述

93 |

1.1 简介

94 | 95 | - 聚合支付SDK Python版本,请使用Python3 。 96 | 97 |

1.2 如何获取

98 | 99 | 100 | [demo源码](https://github.com/ipaynowORG/ipaynow_pay_python.git) 101 | 102 |

1.3 使用说明

103 | 104 | 使用方法: 105 | 106 | 您可以从 GitHub 上下载 Python SDK 的源代码: 107 | 108 | git clone https://github.com/ipaynowORG/ipaynow_pay_python.git 109 | 110 | 1.cd 进入ipaynowPythonSdk 文件夹 111 | 2.执行 "python setup.py install" 112 | 3.在代码中 import ipaynow 113 | 参考示例代码 114 | 示例代码 115 | cd 进入example文件夹 116 | 运行 python tradeTest.py 117 | 118 | 119 | 120 |

2. API

121 | 122 |

2.1 聚合交易API

123 | 124 | 交易模块:trade.py 125 | 126 |
127 | 128 | - 微信被扫支付 129 | 130 | ''' 131 | 微信被扫支付 132 | appId:商户应用id 133 | appKey:商户应用秘钥 134 | mhtOrderDetail:订单详情 135 | notifyUrl:商户后台通知URL 136 | amt:订单金额单位分,默认1分 137 | orderno:订单号(默认系统时间) 138 | channelAuthCode ; 支付授权码 139 | isTest 是否测试 True 测试环境 False 生产环境 140 | ''' 141 | def wx_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 142 | 143 |
144 | 145 | - 支付宝被扫支付 146 | 147 | ''' 148 | 支付宝被扫支付 149 | appId:商户应用id 150 | appKey:商户应用秘钥 151 | mhtOrderDetail:订单详情 152 | notifyUrl:商户后台通知URL 153 | amt:订单金额单位分,默认1分 154 | orderno:订单号(默认系统时间) 155 | channelAuthCode ; 支付授权码 156 | isTest 是否测试 True 测试环境 False 生产环境 157 | ''' 158 | def ali_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 159 |
160 | 161 | - 手Q被扫支付 162 | 163 | ''' 164 | 手Q被扫支付 165 | appId:商户应用id 166 | appKey:商户应用秘钥 167 | mhtOrderDetail:订单详情 168 | notifyUrl:商户后台通知URL 169 | amt:订单金额单位分,默认1分 170 | orderno:订单号(默认系统时间) 171 | channelAuthCode ; 支付授权码 172 | isTest 是否测试 True 测试环境 False 生产环境 173 | ''' 174 | def handq_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 175 | 176 |
177 | 178 | - 京东被扫支付 179 | 180 | ''' 181 | 京东被扫支付 182 | appId:商户应用id 183 | appKey:商户应用秘钥 184 | mhtOrderDetail:订单详情 185 | notifyUrl:商户后台通知URL 186 | amt:订单金额单位分,默认1分 187 | orderno:订单号(默认系统时间) 188 | channelAuthCode ; 支付授权码 189 | isTest 是否测试 True 测试环境 False 生产环境 190 | ''' 191 | def jd_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isest=True) 192 | 193 |
194 | 195 | - 银联被扫支付 196 | 197 | ''' 198 | 银联被扫支付 199 | appId:商户应用id 200 | appKey:商户应用秘钥 201 | mhtOrderDetail:订单详情 202 | notifyUrl:商户后台通知URL 203 | amt:订单金额单位分,默认1分 204 | orderno:订单号(默认系统时间) 205 | channelAuthCode ; 支付授权码 206 | isTest 是否测试 True 测试环境 False 生产环境 207 | ''' 208 | def union_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest) 209 |
210 | 211 | - 微信主扫支付 212 | 213 | ''' 214 | 微信主扫支付 215 | appId:商户应用id 216 | appKey:商户应用秘钥 217 | mhtOrderDetail:订单详情 218 | notifyUrl:商户后台通知URL 219 | amt:订单金额单位分,默认1分 220 | orderno:订单号(默认系统时间) 221 | outputType ; 0 返回二维码串 1 返回支付链接 222 | isTest 是否测试 True 测试环境 False 生产环境 223 | ''' 224 | def wx_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True) 225 |
226 | 227 | - 支付宝主扫支付 228 | 229 | ''' 230 | 支付宝主扫支付 231 | appId:商户应用id 232 | appKey:商户应用秘钥 233 | mhtOrderDetail:订单详情 234 | notifyUrl:商户后台通知URL 235 | amt:订单金额单位分,默认1分 236 | orderno:订单号(默认系统时间) 237 | outputType ; 0 返回二维码串 1 返回支付链接 238 | isTest 是否测试 True 测试环境 False 生产环境 239 | ''' 240 | def ali_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True) 241 |
242 | 243 | - 手Q主扫支付 244 | 245 | ''' 246 | 手Q主扫支付 247 | appId:商户应用id 248 | appKey:商户应用秘钥 249 | mhtOrderDetail:订单详情 250 | notifyUrl:商户后台通知URL 251 | amt:订单金额单位分,默认1分 252 | orderno:订单号(默认系统时间) 253 | outputType ; 0 返回二维码串 1 返回支付链接 254 | isTest 是否测试 True 测试环境 False 生产环境 255 | ''' 256 | def handq_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True) 257 |
258 | 259 | - 京东主扫支付 260 | 261 | ''' 262 | 京东主扫支付 263 | appId:商户应用id 264 | appKey:商户应用秘钥 265 | mhtOrderDetail:订单详情 266 | notifyUrl:商户后台通知URL 267 | amt:订单金额单位分,默认1分 268 | orderno:订单号(默认系统时间) 269 | outputType ; 0 返回二维码串 1 返回支付链接 270 | isTest 是否测试 True 测试环境 False 生产环境 271 | ''' 272 | def jd_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True) 273 |
274 | 275 | - 银联主扫支付 276 | 277 | ''' 278 | 银联主扫支付 279 | appId:商户应用id 280 | appKey:商户应用秘钥 281 | mhtOrderDetail:订单详情 282 | notifyUrl:商户后台通知URL 283 | amt:订单金额单位分,默认1分 284 | orderno:订单号(默认系统时间) 285 | outputType ; 0 返回二维码串 1 返回支付链接 286 | isTest 是否测试 True 测试环境 False 生产环境 287 | ''' 288 | def union_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True) 289 |
290 | 291 | - 微信公众号支付 292 | 293 | ''' 294 | 微信公众号支付 295 | appId:商户应用id 296 | appKey:商户应用秘钥 297 | mhtOrderDetail:订单详情 298 | notifyUrl:商户后台通知URL 299 | frontNotifyUrl :商户前台通知URL 300 | amt:订单金额单位分,默认1分 301 | orderno:订单号(默认系统时间) 302 | outputType ; 0-公众号0模式 303 | isTest 是否测试 True 测试环境 False 生产环境 304 | ''' 305 | def wx_trade0600(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 306 | 307 |
308 | 309 | - 支付宝公众号支付 310 | 311 | ''' 312 | 支付宝公众号支付 313 | appId:商户应用id 314 | appKey:商户应用秘钥 315 | mhtOrderDetail:订单详情 316 | notifyUrl:商户后台通知URL 317 | frontNotifyUrl :商户前台通知URL 318 | amt:订单金额单位分,默认1分 319 | orderno:订单号(默认系统时间) 320 | outputType ; 0-公众号0模式 321 | isTest 是否测试 True 测试环境 False 生产环境 322 | ''' 323 | def ali_trade0600(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 324 | 325 |
326 | 327 | - 手Q公众号支付 328 | 329 | ''' 330 | 手Q公众号支付 331 | appId:商户应用id 332 | appKey:商户应用秘钥 333 | mhtOrderDetail:订单详情 334 | notifyUrl:商户后台通知URL 335 | frontNotifyUrl :商户前台通知URL 336 | amt:订单金额单位分,默认1分 337 | orderno:订单号(默认系统时间) 338 | outputType ; 0-公众号0模式 339 | isTest 是否测试 True 测试环境 False 生产环境 340 | ''' 341 | def handq_trade0600(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 342 | 343 |
344 | 345 | - 微信H5 346 | 347 | ''' 348 | 微信H5支付 349 | appId:商户应用id 350 | appKey:商户应用秘钥 351 | mhtOrderDetail:订单详情 352 | notifyUrl:商户后台通知URL 353 | frontNotifyUrl :商户前台通知URL 354 | amt:订单金额单位分,默认1分 355 | orderno:订单号(默认系统时间) 356 | outputType ; 0-公众号0模式 357 | isTest 是否测试 True 测试环境 False 生产环境 358 | ''' 359 | def wx_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 360 |
361 | 362 | - 支付宝H5 363 | 364 | ''' 365 | 支付宝H5支付 366 | appId:商户应用id 367 | appKey:商户应用秘钥 368 | mhtOrderDetail:订单详情 369 | notifyUrl:商户后台通知URL 370 | frontNotifyUrl :商户前台通知URL 371 | amt:订单金额单位分,默认1分 372 | orderno:订单号(默认系统时间) 373 | outputType ; 0-公众号0模式 374 | isTest 是否测试 True 测试环境 False 生产环境 375 | ''' 376 | def ali_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 377 |
378 | 379 | - 银联H5 380 | 381 | ''' 382 | 银联H5支付 383 | appId:商户应用id 384 | appKey:商户应用秘钥 385 | mhtOrderDetail:订单详情 386 | notifyUrl:商户后台通知URL 387 | frontNotifyUrl :商户前台通知URL 388 | amt:订单金额单位分,默认1分 389 | orderno:订单号(默认系统时间) 390 | outputType ; 0-公众号0模式 391 | isTest 是否测试 True 测试环境 False 生产环境 392 | ''' 393 | def union_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 394 | 395 |
396 | - 招行一网通H5 397 | 398 | ''' 399 | 招行一网通 H5支付 400 | appId:商户应用id 401 | appKey:商户应用秘钥 402 | mhtOrderDetail:订单详情 403 | notifyUrl:商户后台通知URL 404 | frontNotifyUrl :商户前台通知URL 405 | amt:订单金额单位分,默认1分 406 | orderno:订单号(默认系统时间) 407 | outputType ; 0-公众号0模式 408 | isTest 是否测试 True 测试环境 False 生产环境 409 | ''' 410 | def cmbywt_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 411 | 412 |
413 | 414 | 415 | - 手Q H5 416 | 417 | ''' 418 | 手Q H5支付 419 | appId:商户应用id 420 | appKey:商户应用秘钥 421 | mhtOrderDetail:订单详情 422 | notifyUrl:商户后台通知URL 423 | frontNotifyUrl :商户前台通知URL 424 | amt:订单金额单位分,默认1分 425 | orderno:订单号(默认系统时间) 426 | outputType ; 0-公众号0模式 427 | isTest 是否测试 True 测试环境 False 生产环境 428 | ''' 429 | def handq_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True) 430 |
431 | 432 | - 支付宝网页web 433 | 434 | ''' 435 | 支付宝网页web支付 436 | appId:商户应用id 437 | appKey:商户应用秘钥 438 | mhtOrderDetail:订单详情 439 | notifyUrl:商户后台通知URL 440 | frontNotifyUrl :商户前台通知URL 441 | amt:订单金额单位分,默认1分 442 | orderno:订单号(默认系统时间) 443 | outputType:0.返回支付跳转链接 2.返回支付页面(html) 444 | isTest 是否测试 True 测试环境 False 生产环境 445 | ''' 446 | def ali_trade04(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,amt = "1", orderno = '',outputType=0,isTest=True) 447 |
448 | 449 | - 银联网页web 450 | 451 | ''' 452 | 银联网页web支付 453 | appId:商户应用id 454 | appKey:商户应用秘钥 455 | mhtOrderDetail:订单详情 456 | notifyUrl:商户后台通知URL 457 | frontNotifyUrl :商户前台通知URL 458 | amt:订单金额单位分,默认1分 459 | orderno:订单号(默认系统时间) 460 | outputType:0.返回支付跳转链接 2.返回支付页面(html) 461 | isTest 是否测试 True 测试环境 False 生产环境 462 | ''' 463 | def union_trade04(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,amt = "1", orderno = '',outputType=0,isTest=True) 464 |
465 | 466 | - 微信小程序支付 467 | 468 | ''' 469 | 微信小程序 470 | appId:商户应用id 471 | appKey:商户应用秘钥 472 | mhtOrderDetail:订单详情 473 | oriMhtOrderAmt:原始金额 474 | discountAmt:优惠金额 475 | notifyUrl:商户后台通知URL 476 | frontNotifyUrl :商户前台通知URL 477 | amt:订单金额单位分,默认1分 478 | orderno:订单号(默认系统时间) 479 | isTest 是否测试 True 测试环境 False 生产环境 480 | ''' 481 | def wx_app(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,oriMhtOrderAmt,discountAmt,amt = "1", orderno = '',isTest=True) 482 | 483 | 484 | 485 | 486 | 下单接口字段含义如下: 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | 532 | 533 | 534 | 535 | 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 |
字段名称字段Key备注
功能码funcode定值:N001
接口版本号version定值:1.0.0
商户应用唯一标识appId
商户订单号mhtOrderNo
商户商品名称mhtOrderName
商户交易类型mhtOrderType
商户订单币种类型mhtCurrencyType156人民币
商户订单原单金额oriMhtOrderAmt单位(人民币):分
商户订单实付金额mhtOrderAmt单位(人民币):分
商户订单优惠金额discountAmt单位(人民币):分
商户订单超时时间mhtOrderTimeOut60~3600秒,默认3600
商户订单开始时间mhtOrderStartTimeyyyyMMddHHmmss
支付成功时间payTimeyyyyMMddHHmmss
商户字符编码mhtCharsetUTF-8
现在支付流水号nowPayOrderNo
设备类型deviceType
用户所选渠道类型payChannelType12-支付宝 13-微信 27-银联 04-京东 25-手Q
交易支付状态transStatus
渠道订单号channelOrderNo
付款人账号payConsumerId微信返回sub_openid,支付宝返回buyer_user_id
商户保留域mhtReserved给商户使用的字段,商户可以对交易进行标记,现在支付将原样返回
签名方法signType定值:MD5
数据签名signature除signature字段外,所有参数都参与MD5签名
银行类型bankType微信渠道返回
卡类型cardTypeCREDIT 信用卡 DEBIT 借记卡
620 | 621 |

2.2 支付结果通知

622 | 通知方式采用httppost方式通知 623 | 字段含义如下: 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 756 |
字段名称字段Key备注
功能码funcode定值:N001
接口版本号version定值:1.0.0
商户应用唯一标识appId
商户订单号mhtOrderNo
商户商品名称mhtOrderName
商户交易类型mhtOrderType
商户订单币种类型mhtCurrencyType156人民币
商户订单原单金额oriMhtOrderAmt单位(人民币):分
商户订单实付金额mhtOrderAmt单位(人民币):分
商户订单优惠金额discountAmt单位(人民币):分
商户订单超时时间mhtOrderTimeOut60~3600秒,默认3600
商户订单开始时间mhtOrderStartTimeyyyyMMddHHmmss
支付成功时间payTimeyyyyMMddHHmmss
商户字符编码mhtCharsetUTF-8
现在支付流水号nowPayOrderNo
设备类型deviceType
用户所选渠道类型payChannelType
交易支付状态transStatus
渠道订单号channelOrderNo
付款人账号payConsumerId微信返回sub_openid,支付宝返回buyer_user_id
商户保留域mhtReserved给商户使用的字段,商户可以对交易进行标记,现在支付将原样返回
签名方法signType定值:MD5
数据签名signature除signature字段外,所有参数都参与MD5签名
银行类型bankType微信渠道返回
卡类型cardTypeCREDIT 信用卡 DEBIT 借记卡
757 | 758 |

2.3 订单查询API

759 | 模块:queryOrder.py 760 | 761 |
762 | 763 | - 用户主扫支付订单查询 764 | 765 | ''' 766 | 主扫支付订单查询 767 | appId:商户应用id 768 | appKey:商户应用秘钥 769 | orderno:订单号 770 | isTest 是否测试 True 测试环境 False 生产环境 771 | ''' 772 | def query08(appId,appKey,orderno,isTest=True) 773 | 774 |
775 | 776 | - 用户被扫支付订单查询 777 | 778 | ''' 779 | 主扫支付订单查询 780 | appId:商户应用id 781 | appKey:商户应用秘钥 782 | orderno:订单号 783 | isTest 是否测试 True 测试环境 False 生产环境 784 | ''' 785 | def query05(appId,appKey,orderno,isTest=True) 786 | 787 |
788 | 789 | - 公众号支付订单查询 790 | 791 | ''' 792 | 公众号订单查询 793 | appId:商户应用id 794 | appKey:商户应用秘钥 795 | orderno:订单号 796 | isTest 是否测试 True 测试环境 False 生产环境 797 | ''' 798 | def query0600(appId,appKey,orderno,isTest=True) 799 | 800 | 801 |
802 | 803 | - H5支付订单查询 804 | 805 | ''' 806 | H5支付订单查询 807 | appId:商户应用id 808 | appKey:商户应用秘钥 809 | orderno:订单号 810 | isTest 是否测试 True 测试环境 False 生产环境 811 | ''' 812 | def query0601(appId,appKey,orderno,isTest=True) 813 | 814 | 815 | 816 |
817 | 818 | - 网页支付订单查询 819 | 820 | ''' 821 | 网页支付订单查询 822 | appId:商户应用id 823 | appKey:商户应用秘钥 824 | orderno:订单号 825 | isTest 是否测试 True 测试环境 False 生产环境 826 | ''' 827 | def query04(appId,appKey,orderno,isTest=True) 828 | 829 |
830 | 831 | - 小程序支付订单查询 832 | 833 | ''' 834 | 小程序支付订单查询 835 | appId:商户应用id 836 | appKey:商户应用秘钥 837 | orderno:订单号 838 | isTest 是否测试 True 测试环境 False 生产环境 839 | ''' 840 | def query14(appId,appKey,orderno,isTest=True) 841 | 842 | 订单查询接口字段含义如下: 843 | 接口接入URL:https://pay.ipaynow.cn/ 请求类型:POST 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 859 | 860 | 861 | 862 | 863 | 864 | 865 | 866 | 867 | 868 | 869 | 870 | 871 | 872 | 873 | 874 | 875 | 876 | 877 | 878 | 879 | 880 | 881 | 882 | 883 | 884 | 885 | 886 | 887 | 888 | 889 | 890 | 891 |
字段名称字段Key备注
功能码funcode定值:MQ002
接口版本号version定值:1.0.0
商户应用唯一标识appId
设备类型deviceType
商户订单号mhtOrderNo
商户字符集mhtCharset定值:UTF-8
签名方法mhtSignType定值:MD5
数据签名mhtSignature除mhtSignature字段外,所有参数都参与MD5签名。
892 | 893 | 894 |

2.4 退款API

895 | 模块:refund.py 896 | 897 |
898 | 899 | - 退款 900 | 901 | ''' 902 | 退款接口 903 | appId:商户应用id 904 | appKey:商户应用秘钥 905 | orderno:原订单号 906 | mhtRefundNo:商户退款单号 907 | amount:商户退款金额 908 | reason:退款原因 909 | isTest 是否测试 True 测试环境 False 生产环境s 910 | ''' 911 | def refund(appId,appKey,orderno,mhtRefundNo,amount,reason,isTest=True) 912 | 913 |
914 | 915 | - 退款查询 916 | 917 | ''' 918 | 退款查询 919 | appId:商户应用id 920 | appKey:商户应用秘钥 921 | mhtRefundNo:商户退款单号 922 | isTest 是否测试 True 测试环境 False 生产环境 923 | ''' 924 | def refundQuery(appId,appKey,mhtRefundNo,isTest=True) 925 | 926 |
927 | 928 | - 撤销 929 | 930 | ''' 931 | 撤销接口 932 | appId:商户应用id 933 | appKey:商户应用秘钥 934 | orderno:原订单号 935 | mhtRefundNo:商户退款单号 936 | reason:撤销原因 937 | isTest 是否测试 True 测试环境 False 生产环境 938 | ''' 939 | def backOrder(appId,appKey,orderno,mhtRefundNo,reason,isTest=True) 940 | 941 |
942 | 943 | - 撤销查询 944 | 945 | ''' 946 | 撤销查询接口 947 | appId:商户应用id 948 | appKey:商户应用秘钥 949 | mhtRefundNo:商户退款单号 950 | isTest 是否测试 True 测试环境 False 生产环境 951 | ''' 952 | def backOrderQuery(appId,appKey,mhtRefundNo,isTest=True) -------------------------------------------------------------------------------- /example/backOrderQueryTest.py: -------------------------------------------------------------------------------- 1 | from ipaynowPythonSdk.ipaynow.refund import backOrderQuery 2 | 3 | # print(backOrderQuery("xxxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxxx","0rQi6rtXKM1dH")) -------------------------------------------------------------------------------- /example/backOrderTest.py: -------------------------------------------------------------------------------- 1 | from ipaynowPythonSdk.ipaynow.refund import backOrder 2 | 3 | # print(backOrder("xxxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxxxx","0rQi6rtXKM1dH","20171117","测试退款")) -------------------------------------------------------------------------------- /example/queryOrderTest.py: -------------------------------------------------------------------------------- 1 | from ipaynowPythonSdk.ipaynow.queryOrder import queryOrder 2 | 3 | # print (queryOrder("xxxxxxxxxxxxxxxxxx","xxxxxxxxxxxxxxx","eY85WUOEoSP1X")) 4 | 5 | -------------------------------------------------------------------------------- /example/refundTest.py: -------------------------------------------------------------------------------- 1 | from ipaynowPythonSdk.ipaynow.refund import refund 2 | 3 | print(refund("xxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxxxx","xxxxx","20171117","1","测试退款")) -------------------------------------------------------------------------------- /example/tradeTest.py: -------------------------------------------------------------------------------- 1 | from ipaynowPythonSdk.ipaynow.trade import ali_trade08 2 | 3 | print (ali_trade08("xxxxxxxxxxxxxxxxx","xxxxxxxxxxxxxxxxxxxxxx","xxxxxxxxxxxxxx","详情","www.baidu.com",isTest=False)) -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 3 | from ipaynowPythonSdk.ipaynow.version import VERSION 4 | from ipaynowPythonSdk.ipaynow.interface import ( 5 | query, 6 | notify, 7 | # front_notify, 8 | parseTrade, 9 | parseQuery, 10 | parseNotify, 11 | parseFrontNotify 12 | ) 13 | 14 | from ipaynowPythonSdk.ipaynow.error import ( 15 | APIError, 16 | APIInputError 17 | ) 18 | 19 | from ipaynowPythonSdk.ipaynow.utils import trans2unicode 20 | 21 | __all__ = ['trade','query','notify','front_notify','parseTrade','parseQuery','parseNotify','parseFrontNotify','APIError','APIInputError','trans2unicode'] 22 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/error.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 3 | 4 | import getopt, sys 5 | 6 | class IpaynowError(Exception): 7 | def __init__(self, message=None): 8 | super(IpaynowError, self).__init__(message) 9 | self._message = message 10 | def __unicode__(self): 11 | return self._message 12 | 13 | if sys.version_info > (3, 0): 14 | __str__ = lambda self: self.__unicode__() 15 | else: 16 | __str__ = lambda self: unicode(self).encode('utf-8') 17 | 18 | class APIError(IpaynowError): 19 | pass 20 | 21 | class APIInputError(IpaynowError): 22 | pass 23 | 24 | 25 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/interface.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 3 | from ipaynowPythonSdk.ipaynow.packMsg import PackMsgSend 4 | from ipaynowPythonSdk.ipaynow.paramlist import WP001_PostList, WP001_RespList 5 | from ipaynowPythonSdk.ipaynow.paramlist import MQ001_PostList, MQ001_RespList 6 | from ipaynowPythonSdk.ipaynow.paramlist import N001_QueryList, N001_RespList 7 | from ipaynowPythonSdk.ipaynow.paramlist import N002_NotifyList 8 | from ipaynowPythonSdk.ipaynow.unpackMsg import UnpackMsgRecv 9 | from ipaynowPythonSdk.ipaynow.paramlist import MQ001_PostList, R001_PostList, Q001_PostList, R002_PostList, \ 10 | Q002_PostList 11 | 12 | 13 | #下单及查询 14 | proTradeUrl = "https://pay.ipaynow.cn"; 15 | testTradeUrl = "https://dby.ipaynow.cn/api/payment"; 16 | 17 | #退款撤销 18 | proRefundUrl = "https://pay.ipaynow.cn/refund/refundOrder"; 19 | testRefundUrl = "https://dby.ipaynow.cn/refund_access/refundOrder"; 20 | 21 | #退款查询 22 | proRefundQueryUrl = "https://pay.ipaynow.cn/refund/refundQuery"; 23 | testRefundQueryUrl = "https://dby.ipaynow.cn/refund_access/refundQuery"; 24 | 25 | 26 | def trade(appKey,payparam = {}): 27 | 28 | pms = PackMsgSend(appKey,payparam,WP001_PostList) 29 | return pms.getResultString() 30 | 31 | def query(appKey,queryparam = {}): 32 | 33 | pms = PackMsgSend(appKey,queryparam,MQ001_PostList) 34 | return pms.getResultString() 35 | 36 | def refund(appKey,queryparam = {}): 37 | pms = PackMsgSend(appKey,queryparam,R001_PostList) 38 | return pms.getResultString() 39 | 40 | def refundQuery(appKey,queryparam = {}): 41 | pms = PackMsgSend(appKey,queryparam,Q001_PostList) 42 | return pms.getResultString() 43 | 44 | def backOrder(appKey,queryparam = {}): 45 | pms = PackMsgSend(appKey,queryparam,R002_PostList) 46 | return pms.getResultString() 47 | 48 | def backOrderQuery(appKey,queryparam = {}): 49 | pms = PackMsgSend(appKey,queryparam,Q002_PostList) 50 | return pms.getResultString() 51 | 52 | def notify(frontNotifyParam = 'Y'): 53 | stringRtn = "{'success':'%s'}" %frontNotifyParam 54 | return stringRtn 55 | 56 | def parseTrade(instr = ""): 57 | upm = UnpackMsgRecv(instr,WP001_RespList) 58 | recvDict = upm.getResultDict() 59 | isVerified = upm.verifyResponse() 60 | return (recvDict,isVerified) 61 | 62 | def parseQuery(instr = ""): 63 | # instrunicode = trans2unicode(instr) 64 | upm = UnpackMsgRecv(instr,MQ001_RespList) 65 | recvDict = upm.getResultDict() 66 | isVerified = upm.verifyResponse() 67 | return (recvDict,isVerified) 68 | 69 | def parseNotify(instr = ""): 70 | upm = UnpackMsgRecv(instr,N001_QueryList) 71 | recvDict = upm.getResultDict() 72 | isVerified = upm.verifyResponse() 73 | return (recvDict,isVerified) 74 | 75 | def parseFrontNotify(instr = ""): 76 | upm = UnpackMsgRecv(instr,N002_NotifyList) 77 | recvDict = upm.getResultDict() 78 | isVerified = upm.verifyResponse() 79 | return (recvDict,isVerified) 80 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/jsonParseFaced.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ipaynowORG/ipaynow_pay_python/5fc9112e39de1ff86765ee700e63b1a7cf1482c5/ipaynowPythonSdk/ipaynow/jsonParseFaced.py -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/md5Faced.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 2 | 3 | from ipaynowPythonSdk.ipaynow import utils 4 | 5 | __all__ = ['md5calc'] 6 | 7 | try: 8 | import hashlib 9 | except ImportError: 10 | hashlib = None 11 | 12 | if not hashlib: 13 | raise ImportError( 14 | "ipaynow sdk can't import hashlib.please check if it " 15 | ) 16 | 17 | 18 | def md5calc(md5source): 19 | try: 20 | m = hashlib.md5() 21 | m.update(md5source) 22 | return m.hexdigest() 23 | except Exception as e: 24 | print(e.args) 25 | return "" 26 | 27 | if __name__ == "__main__": 28 | strout = "MD5 test string :" 29 | strtest = "" 30 | strout += strtest 31 | strmd5 = md5calc(strtest.encode('utf-8')) 32 | strout += "\nMD5 result string :" + strmd5 33 | print(strout) 34 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/packMsg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 3 | 4 | from ipaynowPythonSdk.ipaynow.paramlist import WP001_PostList 5 | from ipaynowPythonSdk.ipaynow.error import APIInputError 6 | from ipaynowPythonSdk.ipaynow.md5Faced import md5calc 7 | 8 | try: 9 | from urllib import urlencode 10 | except ImportError: 11 | from urllib.parse import urlencode 12 | import getopt, sys 13 | 14 | 15 | def usage(): 16 | print(''' 17 | NAME 18 | pack send message. 19 | Usage 20 | python packMsg.py [options] 21 | ''') 22 | 23 | 24 | class PackMsgSend: 25 | __srcDict = {} 26 | __tarDict = {} 27 | __tarDictJoinMd5 = {} 28 | __tarListJoinMd5 = [] 29 | __filterRule = [] 30 | __fromStrMd5 = "" 31 | # __md5Key = "" 32 | __appKey = "" 33 | __md5Result = "" 34 | 35 | def __init__(self, appKey, sourcedict={}, filterrule=[]): 36 | self.__appKey = appKey 37 | self.__srcDict = sourcedict 38 | self.__filterRule = filterrule 39 | 40 | def __inputFilter(self): 41 | ''' 42 | from __srcDict to __tarDict 43 | use paramlist to filter the input dictionary. 44 | ''' 45 | for singleParam in self.__filterRule: 46 | filedName = singleParam['name'] 47 | # judeg if the filedName exist in source dictionary. 48 | if filedName in self.__srcDict: # exist 49 | # the filedName is exist in sourcedict. 50 | # then judge if the length is right. 51 | srcContent = self.__srcDict[filedName] 52 | if (len(str(srcContent)) > singleParam['len']): 53 | errmsg = '''Your input parameter [{}] is too long. Max length is [{}].'''.format(filedName, 54 | singleParam['len']) 55 | raise APIInputError(errmsg) 56 | if (len(str(srcContent)) == 0): 57 | continue 58 | self.__tarDict[filedName] = srcContent 59 | # if the info needs md5 calc . 60 | if (singleParam['md5'] == 'Y'): 61 | self.__tarDictJoinMd5[filedName] = srcContent 62 | else: # no exist 63 | # judge if the parameter is mandatory 64 | if singleParam['mandatory'] == 'Y': # this parameter is mandatory 65 | if filedName == 'mhtSignature': 66 | continue 67 | errmsg = '''You should input parameter [{}].this parameter indicts [{}].'''.format(filedName, 68 | singleParam[ 69 | 'desp']) 70 | raise APIInputError(errmsg) 71 | else: 72 | continue 73 | self.__sortDict() 74 | 75 | def __sortDict(self): 76 | sortedListJoinmd5 = sorted(self.__tarDictJoinMd5.items(), key=lambda e: e[0], reverse=False) 77 | self.__tarListJoinMd5 = sortedListJoinmd5 78 | 79 | def __createFromStr(self): 80 | fromstrmd5 = "" 81 | for formContentMd5 in self.__tarListJoinMd5: 82 | if formContentMd5[1] == '' or formContentMd5[1] == None: 83 | continue 84 | fromstrmd5 += str(formContentMd5[0]) + "=" + str(formContentMd5[1]) + "&" 85 | self.__fromStrMd5 = fromstrmd5 86 | 87 | def __calcMd5(self): 88 | # remove string that don't join md5 calc 89 | sourceString = self.__fromStrMd5 90 | securityKeyMd5 = md5calc(self.__appKey.encode('utf-8')) 91 | sourceString += securityKeyMd5 92 | # print("待签名字符串:{}".format(sourceString)) 93 | md5Result = md5calc(sourceString.encode('utf_8')) 94 | self.__tarDict['mhtSignature'] = md5Result 95 | self.__md5Result = md5Result 96 | 97 | def getResultString(self): 98 | self.__inputFilter() 99 | self.__createFromStr() 100 | self.__calcMd5() 101 | resultStr = urlencode(self.__tarDict) 102 | return resultStr 103 | 104 | def test(self): 105 | # print("__fromstr :",self.__fromStr) 106 | # print("__fromstrmd5 :",self.__fromStrMd5) 107 | # print("__tarDict :",self.__tarDict) 108 | # print("__tarDictJoinMd5 :",self.__tarDictJoinMd5) 109 | pass 110 | 111 | 112 | if __name__ == '__main__': 113 | try: 114 | opts, args = getopt.getopt(sys.argv[1:], "hf:", ["help", "file="]) 115 | except getopt.GetoptError as err: 116 | # print help information and exit: 117 | print(str(err)) # will print something like "option -a not recognized" 118 | usage() 119 | sys.exit(2) 120 | 121 | file = "" 122 | 123 | for o, a in opts: 124 | if o in ("-h", "--help"): 125 | usage() 126 | sys.exit() 127 | elif o in ("-f", "--file"): 128 | file = a 129 | else: 130 | assert False, "unhandled option" 131 | paypara = { 132 | 'funcode': 'WP001', 133 | 'version': '1.0.0', 134 | 'appId': '150753082825470', 135 | 'mhtOrderType': '01', 136 | 'mhtCurrencyType': '156', 137 | 'mhtOrderDetail': 'ipaynowPythonSDKTestOrder', 138 | 'mhtOrderTimeOut': 3600, 139 | 'notifyUrl': 'http://posp.ipaynow.cn:10808/cpgatetest/notify', 140 | 'mhtCharset': 'UTF-8', 141 | 'deviceType': '05', 142 | 'payChannelType': '13', 143 | 'channelAuthCode': '134954669523328956', 144 | 'mhtReserved': '', 145 | 'consumerId': '', 146 | 'mhtSignType': 'MD5' 147 | } 148 | import time 149 | 150 | timestr = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time())) 151 | paypara['mhtOrderStartTime'] = '20171027101225' 152 | try: 153 | pms = PackMsgSend("8jTST7ywIBY0QQ3RlcxWEl08Xj9gaYyQ", paypara, WP001_PostList) 154 | resultStr = pms.getResultString() 155 | print(resultStr) 156 | except APIInputError as e: 157 | print(e) 158 | 159 | print("============") 160 | # print(quote_plus(resultStr,safe='=&')) 161 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/paramlist.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 3 | 4 | # define interface parameter attributes and max len 5 | 6 | # key name 'name' indicates parameter name 7 | # key name 'must' indicates parameter 8 | # WP001-无插件聚合支付 9 | WP001_PostList = [ 10 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "功能码"}, 11 | {'name': 'version', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "版本1.0.0"}, 12 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 13 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户订单号"}, 14 | {'name': 'mhtOrderName', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户商品名称"}, 15 | {'name': 'mhtOrderType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户交易类型"}, 16 | {'name': 'mhtCurrencyType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 3, 'desp': "商户订单币种类型"}, 17 | {'name': 'mhtOrderAmt', 'mandatory': 'Y', 'md5': 'Y', 'type': 'num', 'len': 22, 'desp': "商户订单交易金额"}, 18 | {'name': 'mhtOrderDetail', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 200, 'desp': "商户订单详情"}, 19 | {'name': 'mhtOrderTimeOut', 'mandatory': 'N', 'md5': 'Y', 'type': 'num', 'len': 4, 'desp': "商户订单超时时间"}, 20 | {'name': 'mhtOrderStartTime', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 14, 'desp': "商户订单开始时间"}, 21 | {'name': 'notifyUrl', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 200, 'desp': "商户后台通知URL"}, 22 | {'name': 'frontNotifyUrl', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 200, 'desp': "商户前台通知URL"}, 23 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 16, 'desp': "商户字符编码-UTF8"}, 24 | {'name': 'deviceType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "设备类型"}, 25 | {'name': 'payChannelType', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "用户所选渠道类型"}, 26 | {'name': 'channelAuthCode', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 20, 'desp': "渠道编号"}, 27 | {'name': 'mhtReserved', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 100, 'desp': "商户保留域"}, 28 | {'name': 'consumerId', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "消费者ID"}, 29 | {'name': 'outputType', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "输出格式"}, 30 | {'name': 'mhtSubAppId', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 64, 'desp': "公众号appId"}, 31 | {'name': 'mhtSignType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 3, 'desp': "商户签名方法-MD5"}, 32 | {'name': 'mhtSignature', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 64, 'desp': "商户数据签名"} 33 | 34 | ] 35 | # 接口接入URL:https://api.ipaynow.cn 请求类型:POST 36 | 37 | # WP001-无插件聚合支付 Response 38 | # 支付交易同步返回 39 | WP001_RespList = [ 40 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 4, 'desp': "功能码"}, 41 | {'name': 'version', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "版本1.0.0"}, 42 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 43 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 40, 'desp': "商户订单号"}, 44 | {'name': 'responseTime', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 40, 'desp': "响应时间"}, 45 | {'name': 'responseCode', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 4, 'desp': "响应码"}, 46 | {'name': 'responseMsg', 'mandatory': 'N', 'md5': 'N', 'type': 'str', 'len': 100, 'desp': "响应信息"}, 47 | {'name': 'nowPayOrderNo', 'mandatory': 'N', 'md5': 'N', 'type': 'str', 'len': 40, 'desp': "现在支付订单号(TN)"} 48 | ] 49 | 50 | # MQ002-商户支付订单查询 51 | # 接口接入URL:https://api.ipaynow.cn 请求类型:POST 由商户发起 52 | MQ001_PostList = [ 53 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "功能码"}, 54 | {'name': 'version', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "版本1.0.0"}, 55 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 56 | {'name': 'deviceType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "设备类型"}, 57 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户订单号"}, 58 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "商户字符集"}, 59 | {'name': 'mhtSignType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 60 | {'name': 'mhtSignature', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 64, 'desp': "数据签名"} 61 | ] 62 | 63 | # R001-退款接口 64 | # 接口接入URL:https://pay.ipaynow.cn/refund/refundOrder 请求类型:POST 65 | R001_PostList = [ 66 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "功能码"}, 67 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 68 | {'name': 'mhtRefundNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户退款单号"}, 69 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "原商户订单号"}, 70 | {'name': 'amount', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 10, 'desp': "商户退款金额"}, 71 | {'name': 'reason', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 256, 'desp': "退款原因"}, 72 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "商户字符集"}, 73 | {'name': 'signType', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 74 | {'name': 'mhtSignature', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 64, 'desp': "数据签名"} 75 | ] 76 | 77 | 78 | # Q001-退款查询接口 79 | # 接口接入URL:https://pay.ipaynow.cn/refund/refundQuery 80 | Q001_PostList = [ 81 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "功能码"}, 82 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 83 | {'name': 'mhtRefundNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户退款单号"}, 84 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "商户字符集"}, 85 | {'name': 'signType', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 86 | {'name': 'mhtSignature', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 64, 'desp': "数据签名"} 87 | ] 88 | 89 | 90 | # R002-撤销接口 91 | # 接口接入URL:https://pay.ipaynow.cn/refund/refundOrder 请求类型:POST 92 | R002_PostList = [ 93 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "功能码"}, 94 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 95 | {'name': 'mhtRefundNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户退款单号"}, 96 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "原商户订单号"}, 97 | {'name': 'reason', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 256, 'desp': "退款原因"}, 98 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "商户字符集"}, 99 | {'name': 'signType', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 100 | {'name': 'mhtSignature', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 64, 'desp': "数据签名"} 101 | ] 102 | 103 | 104 | # Q001-退款查询接口 105 | # 接口接入URL:https://pay.ipaynow.cn/refund/refundQuery 106 | Q002_PostList = [ 107 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "功能码"}, 108 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 109 | {'name': 'mhtRefundNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户撤销单号"}, 110 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "商户字符集"}, 111 | {'name': 'signType', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 112 | {'name': 'mhtSignature', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 64, 'desp': "数据签名"} 113 | ] 114 | 115 | # MQ001-商户支付订单查询 Response 116 | # 支付交易同步返回 117 | MQ001_RespList = [ 118 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 119 | {'name': 'version', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "版本1.0.0"}, 120 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户订单号"}, 121 | {'name': 'mhtOrderName', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户商品名称"}, 122 | {'name': 'mhtOrderType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "订单交易类型"}, 123 | {'name': 'mhtCurrencyType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 3, 'desp': "订单币种类型"}, 124 | {'name': 'mhtOrderAmt', 'mandatory': 'Y', 'md5': 'Y', 'type': 'num', 'len': 22, 'desp': "订单交易金额"}, 125 | {'name': 'mhtOrderTimeOut', 'mandatory': 'N', 'md5': 'Y', 'type': 'num', 'len': 4, 'desp': "订单超时时间"}, 126 | {'name': 'mhtOrderStartTime', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 14, 'desp': "订单开始时间"}, 127 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "交易字符编码"}, 128 | {'name': 'deviceType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "设备类型"}, 129 | {'name': 'payChannelType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "用户所选渠道类型"}, 130 | {'name': 'fee', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 22, 'desp': "交易手续费"}, 131 | {'name': 'settleAmt', 'mandatory': 'N', 'md5': 'Y', 'type': 'num', 'len': 22, 'desp': "商户结算金额"}, 132 | {'name': 'transStatus', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "交易状态"}, 133 | {'name': 'responseTime', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 14, 'desp': "响应时间"}, 134 | {'name': 'responseCode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "响应码"}, 135 | {'name': 'responseMsg', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 100, 'desp': "响应信息"}, 136 | {'name': 'signType', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 137 | {'name': 'signature', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 64, 'desp': "数据签名"} 138 | ] 139 | 140 | # N001-商户服务器端支付结果通知 141 | # 现在支付的聚合支付服务端异步发起: --通讯方式:HTTP POST 方式-- 142 | N001_QueryList = [ 143 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "功能码"}, 144 | {'name': 'version', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "版本1.0.0"}, 145 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 146 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户订单号"}, 147 | {'name': 'mhtOrderName', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户商品名称"}, 148 | {'name': 'mhtOrderType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "商户交易类型"}, 149 | {'name': 'mhtCurrencyType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 3, 'desp': "商户订单币种类型"}, 150 | {'name': 'mhtOrderAmt', 'mandatory': 'Y', 'md5': 'Y', 'type': 'num', 'len': 22, 'desp': "商户订单交易金额"}, 151 | {'name': 'mhtOrderTimeOut', 'mandatory': 'N', 'md5': 'Y', 'type': 'num', 'len': 4, 'desp': "商户订单超时时间"}, 152 | {'name': 'mhtOrderStartTime', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 14, 'desp': "商户订单开始时间"}, 153 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "商户字符编码"}, 154 | {'name': 'deviceType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "设备类型"}, 155 | {'name': 'payChannelType', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 2, 'desp': "用户所选渠道类型"}, 156 | {'name': 'nowPayOrderNo', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 64, 'desp': "现在支付账号"}, 157 | {'name': 'tradeStatus', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "交易支付状态"}, 158 | {'name': 'mhtReserved', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 100, 'desp': "商户保留域"}, 159 | {'name': 'signType', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 160 | {'name': 'signature', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 64, 'desp': "数据签名"}, 161 | {'name': 'channelOrderNo', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 100, 'desp': "渠道订单号"} 162 | ] 163 | 164 | # N001-商户服务器端支付结果通知 Resp 165 | N001_RespList = [ 166 | {'name': 'success', 'mandatory': 'Y', 'md5': 'N', 'type': 'str', 'len': 1, 'desp': "是否成功"} 167 | ] 168 | 169 | # N002-商户前端支付结果通知 170 | N002_NotifyList = [ 171 | {'name': 'funcode', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "功能码"}, 172 | {'name': 'version', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 5, 'desp': "版本1.0.0"}, 173 | {'name': 'appId', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户应用唯一标识"}, 174 | {'name': 'mhtOrderNo', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 40, 'desp': "商户订单号"}, 175 | {'name': 'mhtCharset', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "商户字符编码"}, 176 | {'name': 'tradeStatus', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 4, 'desp': "交易支付状态"}, 177 | {'name': 'mhtReserved', 'mandatory': 'N', 'md5': 'Y', 'type': 'str', 'len': 100, 'desp': "商户保留域"}, 178 | {'name': 'signType', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 6, 'desp': "签名方法"}, 179 | {'name': 'signature', 'mandatory': 'Y', 'md5': 'Y', 'type': 'str', 'len': 64, 'desp': "数据签名"}, 180 | ] 181 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/queryOrder.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | import urllib 4 | from datetime import time 5 | 6 | from pip._vendor import requests 7 | 8 | from ipaynowPythonSdk.ipaynow import interface 9 | from ipaynowPythonSdk.ipaynow.interface import proTradeUrl, testTradeUrl 10 | 11 | ''' 12 | 主扫支付订单查询 13 | appId:商户应用id 14 | appKey:商户应用秘钥 15 | orderno:订单号 16 | isTest 是否测试 True 测试环境 False 生产环境 17 | ''' 18 | def query08(appId,appKey,orderno,isTest=True): 19 | return queryOrder(appId,appKey,"08",orderno,isTest) 20 | 21 | ''' 22 | 被扫支付订单查询 23 | appId:商户应用id 24 | appKey:商户应用秘钥 25 | orderno:订单号 26 | isTest 是否测试 True 测试环境 False 生产环境 27 | ''' 28 | def query05(appId,appKey,orderno,isTest=True): 29 | return queryOrder(appId,appKey,"05",orderno,isTest) 30 | 31 | 32 | ''' 33 | 网页支付订单查询 34 | appId:商户应用id 35 | appKey:商户应用秘钥 36 | orderno:订单号 37 | isTest 是否测试 True 测试环境 False 生产环境 38 | ''' 39 | def query04(appId,appKey,orderno,isTest=True): 40 | return queryOrder(appId,appKey,"04",orderno,isTest) 41 | 42 | ''' 43 | 公众号支付订单查询 44 | appId:商户应用id 45 | appKey:商户应用秘钥 46 | orderno:订单号 47 | isTest 是否测试 True 测试环境 False 生产环境 48 | ''' 49 | def query0600(appId,appKey,orderno,isTest=True): 50 | return queryOrder(appId,appKey,"0600",orderno,isTest) 51 | 52 | 53 | ''' 54 | H5支付订单查询 55 | appId:商户应用id 56 | appKey:商户应用秘钥 57 | orderno:订单号 58 | isTest 是否测试 True 测试环境 False 生产环境 59 | ''' 60 | def query0601(appId,appKey,orderno,isTest=True): 61 | return queryOrder(appId,appKey,"0601",orderno,isTest) 62 | 63 | ''' 64 | 小程序支付订单查询 65 | appId:商户应用id 66 | appKey:商户应用秘钥 67 | orderno:订单号 68 | isTest 是否测试 True 测试环境 False 生产环境 69 | ''' 70 | def query14(appId,appKey,orderno,isTest=True): 71 | return queryOrder(appId,appKey,"14",orderno,isTest) 72 | 73 | 74 | def queryOrder(appId,appKey,deviceType, orderno,isTest): 75 | paypara = { 76 | 'funcode':'MQ002', 77 | 'version': '1.0.0', 78 | 'appId':appId, 79 | 'mhtCharset': 'UTF-8', 80 | 'deviceType': deviceType, 81 | 'mhtSignType':'MD5', 82 | 'mhtOrderNo':orderno 83 | 84 | } 85 | try: 86 | tradestr = interface.query(appKey,paypara) 87 | except interface.APIInputError as ipse: 88 | print(ipse) 89 | except Exception as e: 90 | print(e) 91 | print(e.with_traceback) 92 | if isTest: 93 | url = testTradeUrl 94 | else: 95 | url = proTradeUrl 96 | resp = requests.post(url,tradestr) 97 | return urllib.parse.unquote(resp.text) -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/refund.py: -------------------------------------------------------------------------------- 1 | import urllib 2 | 3 | from pip._vendor import requests 4 | 5 | from ipaynowPythonSdk.ipaynow import interface 6 | 7 | 8 | import urllib 9 | 10 | from pip._vendor import requests 11 | 12 | from ipaynowPythonSdk.ipaynow import interface 13 | from ipaynowPythonSdk.ipaynow.interface import testRefundUrl, proRefundUrl, testRefundQueryUrl, proRefundQueryUrl 14 | 15 | ''' 16 | 撤销查询接口 17 | appId:商户应用id 18 | appKey:商户应用秘钥 19 | mhtRefundNo:商户退款单号 20 | isTest 是否测试 True 测试环境 False 生产环境 21 | ''' 22 | def backOrderQuery(appId,appKey,mhtRefundNo,isTest=True): 23 | paypara = { 24 | 'funcode':'Q002', 25 | 'appId':appId, 26 | 'mhtCharset': 'UTF-8', 27 | 'signType':'MD5', 28 | 'mhtRefundNo':mhtRefundNo 29 | } 30 | try: 31 | refundstr = interface.backOrderQuery(appKey,paypara) 32 | except interface.APIInputError as ipse: 33 | print(ipse) 34 | except Exception as e: 35 | print(e) 36 | print(e.with_traceback) 37 | if isTest: 38 | url = testRefundUrl 39 | else: 40 | url = proRefundUrl 41 | resp = requests.post(url,refundstr) 42 | return urllib.parse.unquote(resp.text) 43 | 44 | ''' 45 | 撤销接口 46 | appId:商户应用id 47 | appKey:商户应用秘钥 48 | orderno:原订单号 49 | mhtRefundNo:商户退款单号 50 | reason:撤销原因 51 | isTest 是否测试 True 测试环境 False 生产环境 52 | ''' 53 | def backOrder(appId,appKey,orderno,mhtRefundNo,reason,isTest=True): 54 | paypara = { 55 | 'funcode':'R002', 56 | 'appId':appId, 57 | 'mhtCharset': 'UTF-8', 58 | 'reason': reason, 59 | 'signType':'MD5', 60 | 'mhtOrderNo':orderno, 61 | 'mhtRefundNo':mhtRefundNo 62 | } 63 | try: 64 | refundstr = interface.backOrder(appKey,paypara) 65 | except interface.APIInputError as ipse: 66 | print(ipse) 67 | except Exception as e: 68 | print(e) 69 | print(e.with_traceback) 70 | if isTest: 71 | url = testRefundUrl 72 | else: 73 | url = proRefundUrl 74 | print(refundstr) 75 | resp = requests.post(url,refundstr) 76 | return urllib.parse.unquote(resp.text) 77 | 78 | 79 | ''' 80 | 退款查询 81 | appId:商户应用id 82 | appKey:商户应用秘钥 83 | mhtRefundNo:商户退款单号 84 | isTest 是否测试 True 测试环境 False 生产环境 85 | ''' 86 | def refundQuery(appId,appKey,mhtRefundNo,isTest=True): 87 | paypara = { 88 | 'funcode':'Q001', 89 | 'appId':appId, 90 | 'mhtCharset': 'UTF-8', 91 | 'signType':'MD5', 92 | 'mhtRefundNo':mhtRefundNo 93 | } 94 | try: 95 | refundstr = interface.refundQuery(appKey,paypara) 96 | except interface.APIInputError as ipse: 97 | print(ipse) 98 | except Exception as e: 99 | print(e) 100 | print(e.with_traceback) 101 | if isTest: 102 | url = testRefundQueryUrl 103 | else: 104 | url = proRefundQueryUrl 105 | resp = requests.post(url,refundstr) 106 | return urllib.parse.unquote(resp.text) 107 | 108 | 109 | ''' 110 | 退款接口 111 | appId:商户应用id 112 | appKey:商户应用秘钥 113 | orderno:原订单号 114 | mhtRefundNo:商户退款单号 115 | amount:商户退款金额 116 | reason:退款原因 117 | isTest 是否测试 True 测试环境 False 生产环境 118 | ''' 119 | def refund(appId,appKey,orderno,mhtRefundNo,amount,reason,isTest = True): 120 | paypara = { 121 | 'funcode':'R001', 122 | 'appId':appId, 123 | 'mhtCharset': 'UTF-8', 124 | 'amount': amount, 125 | 'reason': reason, 126 | 'signType':'MD5', 127 | 'mhtOrderNo':orderno, 128 | 'mhtRefundNo':mhtRefundNo 129 | } 130 | try: 131 | refundstr = interface.refund(appKey,paypara) 132 | except interface.APIInputError as ipse: 133 | print(ipse) 134 | except Exception as e: 135 | print(e) 136 | print(e.with_traceback) 137 | if isTest: 138 | url = testRefundUrl 139 | else: 140 | url = proRefundUrl 141 | resp = requests.post(url,refundstr) 142 | return urllib.parse.unquote(resp.text) -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/trade.py: -------------------------------------------------------------------------------- 1 | import random 2 | import string 3 | import time 4 | import urllib 5 | 6 | from ipaynowPythonSdk.ipaynow import interface 7 | from pip._vendor import requests 8 | 9 | from ipaynowPythonSdk.ipaynow.interface import testTradeUrl, proTradeUrl 10 | 11 | ''' 12 | 微信公众号支付 13 | appId:商户应用id 14 | appKey:商户应用秘钥 15 | mhtOrderDetail:订单详情 16 | notifyUrl:商户后台通知URL 17 | frontNotifyUrl :商户前台通知URL 18 | isTest 是否测试 True 测试环境 False 生产环境 19 | amt:订单金额单位分,默认1分 20 | orderno:订单号(默认系统时间) 21 | outputType ; 0-公众号0模式 22 | ''' 23 | def wx_trade0600(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 24 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,payChannelType="13",deviceType="0600",amt = amt, orderno = orderno,outputType=outputType) 25 | 26 | ''' 27 | 支付宝公众号支付 28 | appId:商户应用id 29 | appKey:商户应用秘钥 30 | mhtOrderDetail:订单详情 31 | notifyUrl:商户后台通知URL 32 | frontNotifyUrl :商户前台通知URL 33 | isTest 是否测试 True 测试环境 False 生产环境 34 | amt:订单金额单位分,默认1分 35 | orderno:订单号(默认系统时间) 36 | outputType ; 0-公众号0模式 37 | ''' 38 | def ali_trade0600(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 39 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,frontNotifyUrl=frontNotifyUrl,payChannelType="12",deviceType="0600",amt = amt, orderno = orderno,outputType=outputType) 40 | 41 | 42 | ''' 43 | 手Q公众号支付 44 | appId:商户应用id 45 | appKey:商户应用秘钥 46 | mhtOrderDetail:订单详情 47 | notifyUrl:商户后台通知URL 48 | frontNotifyUrl :商户前台通知URL 49 | isTest 是否测试 True 测试环境 False 生产环境 50 | amt:订单金额单位分,默认1分 51 | orderno:订单号(默认系统时间) 52 | outputType ; 0-公众号0模式 53 | ''' 54 | def handq_trade0600(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 55 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,payChannelType="25",deviceType="0600",amt = amt, orderno = orderno,outputType=outputType) 56 | 57 | ''' 58 | 微信主扫支付 59 | appId:商户应用id 60 | appKey:商户应用秘钥 61 | mhtOrderDetail:订单详情 62 | notifyUrl:商户后台通知URL 63 | isTest 是否测试 True 测试环境 False 生产环境 64 | amt:订单金额单位分,默认1分 65 | orderno:订单号(默认系统时间) 66 | outputType ; 0 返回二维码串 1 返回支付链接 67 | ''' 68 | def wx_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True): 69 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="13",deviceType="08",amt = amt, orderno = orderno,outputType=outputType) 70 | 71 | 72 | ''' 73 | 支付宝主扫支付 74 | appId:商户应用id 75 | appKey:商户应用秘钥 76 | mhtOrderDetail:订单详情 77 | notifyUrl:商户后台通知URL 78 | amt:订单金额单位分,默认1分 79 | orderno:订单号(默认系统时间) 80 | outputType ; 0 返回二维码串 1 返回支付链接 81 | isTest 是否测试 True 测试环境 False 生产环境 82 | ''' 83 | def ali_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType="0",amt = "1", orderno = '',isTest=True): 84 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="12",deviceType="08",amt = amt, orderno = orderno,outputType=outputType) 85 | 86 | ''' 87 | 手Q主扫支付 88 | appId:商户应用id 89 | appKey:商户应用秘钥 90 | mhtOrderDetail:订单详情 91 | notifyUrl:商户后台通知URL 92 | isTest 是否测试 True 测试环境 False 生产环境 93 | amt:订单金额单位分,默认1分 94 | orderno:订单号(默认系统时间) 95 | outputType ; 0 返回二维码串 1 返回支付链接 96 | ''' 97 | def handq_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True): 98 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="25",deviceType="08",amt = amt, orderno = orderno,outputType=outputType) 99 | 100 | ''' 101 | 京东主扫支付 102 | appId:商户应用id 103 | appKey:商户应用秘钥 104 | mhtOrderDetail:订单详情 105 | notifyUrl:商户后台通知URL 106 | isTest 是否测试 True 测试环境 False 生产环境 107 | amt:订单金额单位分,默认1分 108 | orderno:订单号(默认系统时间) 109 | outputType ; 0 返回二维码串 1 返回支付链接 110 | ''' 111 | def jd_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True): 112 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="04",deviceType="08",amt = amt, orderno = orderno,outputType=outputType) 113 | 114 | 115 | ''' 116 | 银联主扫支付 117 | appId:商户应用id 118 | appKey:商户应用秘钥 119 | mhtOrderDetail:订单详情 120 | notifyUrl:商户后台通知URL 121 | isTest 是否测试 True 测试环境 False 生产环境 122 | amt:订单金额单位分,默认1分 123 | orderno:订单号(默认系统时间) 124 | outputType ; 0 返回二维码串 1 返回支付链接 125 | ''' 126 | def union_trade08(appId,appKey,ordername,mhtOrderDetail,notifyUrl,outputType,amt = "1", orderno = '',isTest=True): 127 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="27",deviceType="08",amt = amt, orderno = orderno,outputType=outputType) 128 | 129 | ''' 130 | 微信被扫支付 131 | appId:商户应用id 132 | appKey:商户应用秘钥 133 | mhtOrderDetail:订单详情 134 | notifyUrl:商户后台通知URL 135 | isTest 是否测试 True 测试环境 False 生产环境 136 | amt:订单金额单位分,默认1分 137 | orderno:订单号(默认系统时间) 138 | channelAuthCode ; 支付授权码 139 | ''' 140 | def wx_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 141 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="13",deviceType="05",amt = amt, orderno = orderno,channelAuthCode=channelAuthCode) 142 | 143 | 144 | ''' 145 | 支付宝被扫支付 146 | appId:商户应用id 147 | appKey:商户应用秘钥 148 | mhtOrderDetail:订单详情 149 | notifyUrl:商户后台通知URL 150 | isTest 是否测试 True 测试环境 False 生产环境 151 | amt:订单金额单位分,默认1分 152 | orderno:订单号(默认系统时间) 153 | channelAuthCode ; 支付授权码 154 | ''' 155 | def ali_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 156 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="12",deviceType="05",amt = amt, orderno = orderno,channelAuthCode=channelAuthCode) 157 | 158 | 159 | ''' 160 | 手Q被扫支付 161 | appId:商户应用id 162 | appKey:商户应用秘钥 163 | mhtOrderDetail:订单详情 164 | notifyUrl:商户后台通知URL 165 | isTest 是否测试 True 测试环境 False 生产环境 166 | amt:订单金额单位分,默认1分 167 | orderno:订单号(默认系统时间) 168 | channelAuthCode ; 支付授权码 169 | ''' 170 | def handq_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 171 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="25",deviceType="05",amt = amt, orderno = orderno,channelAuthCode=channelAuthCode) 172 | 173 | 174 | ''' 175 | 京东被扫支付 176 | appId:商户应用id 177 | appKey:商户应用秘钥 178 | mhtOrderDetail:订单详情 179 | notifyUrl:商户后台通知URL 180 | isTest 是否测试 True 测试环境 False 生产环境 181 | amt:订单金额单位分,默认1分 182 | orderno:订单号(默认系统时间) 183 | channelAuthCode ; 支付授权码 184 | ''' 185 | def jd_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 186 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="04",deviceType="05",amt = amt, orderno = orderno,channelAuthCode=channelAuthCode) 187 | 188 | 189 | 190 | ''' 191 | 银联被扫支付 192 | appId:商户应用id 193 | appKey:商户应用秘钥 194 | mhtOrderDetail:订单详情 195 | notifyUrl:商户后台通知URL 196 | isTest 是否测试 True 测试环境 False 生产环境 197 | amt:订单金额单位分,默认1分 198 | orderno:订单号(默认系统时间) 199 | channelAuthCode ; 支付授权码 200 | ''' 201 | def union_trade05(appId,appKey,ordername,mhtOrderDetail,notifyUrl,channelAuthCode,amt = "1", orderno = '',isTest=True): 202 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,isTest=isTest,payChannelType="27",deviceType="05",amt = amt, orderno = orderno,channelAuthCode=channelAuthCode) 203 | 204 | 205 | ''' 206 | 微信H5支付 207 | appId:商户应用id 208 | appKey:商户应用秘钥 209 | mhtOrderDetail:订单详情 210 | notifyUrl:商户后台通知URL 211 | frontNotifyUrl :商户前台通知URL 212 | isTest 是否测试 True 测试环境 False 生产环境 213 | amt:订单金额单位分,默认1分 214 | orderno:订单号(默认系统时间) 215 | outputType ; 0-公众号0模式 216 | ''' 217 | def wx_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 218 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,payChannelType="13",deviceType="0601",amt = amt, orderno = orderno,outputType=outputType) 219 | 220 | 221 | ''' 222 | 支付宝H5支付 223 | appId:商户应用id 224 | appKey:商户应用秘钥 225 | mhtOrderDetail:订单详情 226 | notifyUrl:商户后台通知URL 227 | frontNotifyUrl :商户前台通知URL 228 | isTest 是否测试 True 测试环境 False 生产环境 229 | amt:订单金额单位分,默认1分 230 | orderno:订单号(默认系统时间) 231 | outputType ; 0-公众号0模式 232 | ''' 233 | def ali_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 234 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,payChannelType="12",deviceType="0601",amt = amt, orderno = orderno,outputType=outputType) 235 | 236 | ''' 237 | 银联H5支付 238 | appId:商户应用id 239 | appKey:商户应用秘钥 240 | mhtOrderDetail:订单详情 241 | notifyUrl:商户后台通知URL 242 | frontNotifyUrl :商户前台通知URL 243 | isTest 是否测试 True 测试环境 False 生产环境 244 | amt:订单金额单位分,默认1分 245 | orderno:订单号(默认系统时间) 246 | outputType ; 0-公众号0模式 247 | ''' 248 | def union_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 249 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,payChannelType="27",deviceType="0601",amt = amt, orderno = orderno,outputType=outputType) 250 | 251 | ''' 252 | 手Q H5支付 253 | appId:商户应用id 254 | appKey:商户应用秘钥 255 | mhtOrderDetail:订单详情 256 | notifyUrl:商户后台通知URL 257 | frontNotifyUrl :商户前台通知URL 258 | isTest 是否测试 True 测试环境 False 生产环境 259 | amt:订单金额单位分,默认1分 260 | orderno:订单号(默认系统时间) 261 | outputType ; 0-公众号0模式 262 | ''' 263 | def handq_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 264 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,payChannelType="12",deviceType="0601",amt = amt, orderno = orderno,outputType=outputType) 265 | 266 | ''' 267 | 招行一网通 H5支付 268 | appId:商户应用id 269 | appKey:商户应用秘钥 270 | mhtOrderDetail:订单详情 271 | notifyUrl:商户后台通知URL 272 | frontNotifyUrl :商户前台通知URL 273 | isTest 是否测试 True 测试环境 False 生产环境 274 | amt:订单金额单位分,默认1分 275 | orderno:订单号(默认系统时间) 276 | outputType ; 0-公众号0模式 277 | ''' 278 | def cmbywt_trade0601(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,outputType,amt = "1", orderno = '',isTest=True): 279 | return trade(appId,appKey,ordername,mhtOrderDetail,notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,payChannelType="17",deviceType="0601",amt = amt, orderno = orderno,outputType=outputType) 280 | 281 | 282 | ''' 283 | 支付宝网页web支付 284 | appId:商户应用id 285 | appKey:商户应用秘钥 286 | mhtOrderDetail:订单详情 287 | notifyUrl:商户后台通知URL 288 | frontNotifyUrl :商户前台通知URL 289 | isTest 是否测试 True 测试环境 False 生产环境 290 | amt:订单金额单位分,默认1分 291 | orderno:订单号(默认系统时间) 292 | outputType:0.返回支付跳转链接 2.返回支付页面(html) 293 | ''' 294 | def ali_trade04(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,amt = "1", orderno = '',outputType=0,isTest=True): 295 | return trade(appId,appKey,ordername,mhtOrderDetail,payChannelType="12",notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,deviceType="04",amt = amt, orderno = orderno,outputType=outputType) 296 | 297 | ''' 298 | 银联网页web支付 299 | appId:商户应用id 300 | appKey:商户应用秘钥 301 | mhtOrderDetail:订单详情 302 | notifyUrl:商户后台通知URL 303 | frontNotifyUrl :商户前台通知URL 304 | isTest 是否测试 True 测试环境 False 生产环境 305 | amt:订单金额单位分,默认1分 306 | orderno:订单号(默认系统时间) 307 | outputType:0.返回支付跳转链接 2.返回支付页面(html) 308 | ''' 309 | def union_trade04(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,amt = "1", orderno = '',outputType=0,isTest=True): 310 | return trade(appId,appKey,ordername,mhtOrderDetail,payChannelType="27",notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,deviceType="04",amt = amt, orderno = orderno,outputType=outputType) 311 | 312 | 313 | ''' 314 | 微信小程序 315 | appId:商户应用id 316 | appKey:商户应用秘钥 317 | mhtOrderDetail:订单详情 318 | oriMhtOrderAmt:原始金额 319 | discountAmt:优惠金额 320 | notifyUrl:商户后台通知URL 321 | isTest 是否测试 True 测试环境 False 生产环境 322 | frontNotifyUrl :商户前台通知URL 323 | amt:订单金额单位分,默认1分 324 | orderno:订单号(默认系统时间) 325 | ''' 326 | def wx_app(appId,appKey,ordername,mhtOrderDetail,notifyUrl,frontNotifyUrl,oriMhtOrderAmt,discountAmt,amt = "1", orderno = '',isTest=True): 327 | return trade(appId,appKey,ordername,mhtOrderDetail,payChannelType="13",notifyUrl=notifyUrl,frontNotifyUrl=frontNotifyUrl,isTest=isTest,deviceType="14",oriMhtOrderAmt=oriMhtOrderAmt,discountAmt=discountAmt,amt = amt, orderno = orderno,outputType="1") 328 | 329 | 330 | def trade(appId,appKey,ordername,mhtOrderDetail,payChannelType,deviceType,notifyUrl,isTest,outputType,frontNotifyUrl="", amt = "1", orderno = '',channelAuthCode='',oriMhtOrderAmt='',discountAmt=''): 331 | paypara = { 332 | 'funcode':'WP001', 333 | 'version': '1.0.0', 334 | 'appId':appId, 335 | 'mhtOrderType' :'01', 336 | 'mhtCurrencyType':'156', 337 | 'mhtOrderDetail':mhtOrderDetail, 338 | 'mhtOrderTimeOut':3600, 339 | 'notifyUrl':notifyUrl, 340 | 'mhtCharset': 'UTF-8', 341 | 'deviceType': deviceType, 342 | 'payChannelType' : payChannelType, 343 | 'outputType':outputType, 344 | 'mhtSignType':'MD5' 345 | 346 | } 347 | if len(frontNotifyUrl) > 0 : 348 | paypara["frontNotifyUrl"] = frontNotifyUrl 349 | if len(channelAuthCode) > 0: 350 | paypara['channelAuthCode']=channelAuthCode 351 | timestr = time.strftime('%Y%m%d%H%M%S',time.localtime(time.time())) 352 | if len(orderno) == 0: 353 | orderno = timestr + '_' +''.join(random.sample(string.ascii_letters, 16)) 354 | paypara['mhtOrderStartTime'] = timestr 355 | paypara['mhtOrderNo'] = orderno 356 | paypara['mhtOrderName'] = ordername 357 | paypara['mhtOrderAmt'] = amt 358 | if len(oriMhtOrderAmt) > 0 : 359 | paypara["oriMhtOrderAmt"] = oriMhtOrderAmt 360 | 361 | if len(discountAmt) > 0 : 362 | paypara["discountAmt"] = discountAmt 363 | try: 364 | tradestr = interface.trade(appKey,paypara) 365 | except interface.APIInputError as ipse: 366 | print(ipse) 367 | except Exception as e: 368 | print(e) 369 | print(e.with_traceback) 370 | if isTest: 371 | url = testTradeUrl 372 | else: 373 | url = proTradeUrl 374 | resp = requests.post(url,tradestr) 375 | return urllib.parse.unquote(resp.text) -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/unpackMsg.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 3 | try: 4 | import sys 5 | reload(sys) 6 | sys.setdefaultencoding( "utf-8" ) 7 | except Exception: 8 | pass 9 | 10 | # WP001-无插件聚合支付 11 | from ipaynowPythonSdk.ipaynow.paramlist import WP001_PostList, WP001_RespList 12 | # MQ001-商户支付订单查询 13 | from ipaynowPythonSdk.ipaynow.paramlist import MQ001_PostList, MQ001_RespList 14 | # N001-商户服务器端支付结果通知 15 | from ipaynowPythonSdk.ipaynow.paramlist import N001_QueryList, N001_RespList 16 | # N002-商户前端支付结果通知 17 | from ipaynowPythonSdk.ipaynow.paramlist import N002_NotifyList 18 | 19 | import ipaynowPythonSdk.ipaynow 20 | from ipaynowPythonSdk.ipaynow.error import APIInputError 21 | from ipaynowPythonSdk.ipaynow.md5Faced import md5calc 22 | from ipaynowPythonSdk.ipaynow.utils import trans2unicode 23 | 24 | try: 25 | from urllib import unquote 26 | except ImportError: 27 | from urllib.parse import unquote 28 | 29 | import getopt, sys 30 | def usage(): 31 | print (''' 32 | NAME 33 | pack send message. 34 | Usage 35 | python packMsg.py [options] 36 | ''') 37 | 38 | 39 | class UnpackMsgRecv: 40 | __recvStr = "" 41 | __filterRule = [] 42 | __apiKey = "" 43 | __unpackDict = {} 44 | __recvSortedList = [] 45 | __md5Dict = {} 46 | __tarDictJoinMd5 = {} 47 | __md5Result = "" 48 | __tarListJoinMd5 = [] 49 | __fromStrMd5 = "" 50 | def __init__(self, recvStr = "", filterrule = []): 51 | unicodestr = trans2unicode(recvStr) 52 | self.__recvStr = unquote(unicodestr) 53 | self.__filterRule = filterrule 54 | self.__apiKey = ipaynow.api_key 55 | def __recvStr2Dict(self): 56 | tempDict = {} 57 | tempList = self.__recvStr.split("&") 58 | for onpair in tempList: 59 | pairList = onpair.split("=") 60 | tempDict[pairList[0]] = pairList[1] 61 | self.__unpackDict = tempDict 62 | def __recvFilter(self): 63 | """from __unpackDict to __md5Dict. 64 | Use paramlist to filter the input dictionary. 65 | """ 66 | for singleParam in self.__filterRule: 67 | filedName = singleParam['name'] 68 | # judeg if the filedName exist in source dictionary. 69 | if filedName in self.__unpackDict: #exist 70 | # the filedName is exist in sourcedict. 71 | # then judge if the length is right. 72 | srcContent = self.__unpackDict[filedName] 73 | if ( len(str(srcContent)) > singleParam['len']): 74 | errmsg = '''Recv parameter [{}] is too long. Max length is [{}].'''.format(filedName,singleParam['len']) 75 | raise APIInputError(errmsg) 76 | if (len(str(srcContent)) == 0): 77 | continue 78 | # self.__tarDict[filedName] = srcContent 79 | # if the info needs md5 calc . 80 | if (singleParam['md5'] == 'Y'): 81 | self.__tarDictJoinMd5[filedName] = srcContent 82 | else : # no exist 83 | # judge if the parameter is mandatory 84 | if singleParam['mandatory'] == 'Y': # this parameter is mandatory 85 | if filedName == 'mhtSignature': 86 | continue 87 | errmsg = '''Didn't receive parameter [{}].this parameter indicts [{}].'''.format(filedName,singleParam['desp']) 88 | raise APIInputError(errmsg) 89 | else: 90 | continue 91 | def __sortDict(self, ): 92 | sortedListJoinmd5 = sorted(self.__tarDictJoinMd5.items(),key = lambda e: e[0],reverse = False) 93 | self.__tarListJoinMd5 = sortedListJoinmd5 94 | def __createFromStr(self): 95 | fromstrmd5 = "" 96 | for formContentMd5 in self.__tarListJoinMd5: 97 | if formContentMd5[1] == '' or formContentMd5[1] == None: 98 | continue 99 | fromstrmd5 += str(formContentMd5[0]) + "=" + str(formContentMd5[1]) + "&" 100 | self.__fromStrMd5 = fromstrmd5 101 | def __calcMd5(self): 102 | sourceString = self.__fromStrMd5 103 | securityKeyMd5 = md5calc(self.__apiKey.encode('utf-8')) 104 | sourceString += securityKeyMd5 105 | # print("待签名字符串:{}".format(sourceString)) 106 | md5Result = md5calc(sourceString.encode('utf_8')) 107 | self.__md5Result = md5Result 108 | def getResultDict(self): 109 | self.__recvStr2Dict() 110 | return self.__unpackDict 111 | def verifyResponse(self): 112 | if not self.__unpackDict: # assert dictionary is exist. 113 | self.__recvStr2Dict() 114 | # start calc the md5 string 115 | self.__recvFilter() 116 | self.__sortDict() 117 | self.__createFromStr() 118 | self.__calcMd5() 119 | # print("calc md5 string:") 120 | #print(self.__md5Result) 121 | # print("signature:") 122 | # print(self.__unpackDict["signature"]) 123 | return self.__md5Result == self.__unpackDict["signature"] 124 | def test(self): 125 | pass 126 | if __name__ == '__main__': 127 | try: 128 | opts, args = getopt.getopt(sys.argv[1:], "hf:", ["help", "file="]) 129 | except getopt.GetoptError as err: 130 | # print help information and exit: 131 | print( str(err)) # will print something like "option -a not recognized" 132 | usage() 133 | sys.exit(2) 134 | 135 | file="" 136 | 137 | for o, a in opts: 138 | if o in ("-h", "--help"): 139 | usage() 140 | sys.exit() 141 | elif o in ("-f", "--file"): 142 | file= a 143 | else: 144 | assert False, "unhandled option" 145 | recvStr = '''mhtCharset=UTF-8&responseCode=A001&payChannelType=12&appId=1409801351286401&mhtOrderStartTime=20151102100843&mhtOrderNo=20151102100843_LAzqDtZklJhwmdBO&signType=MD5&mhtOrderAmt=10&transStatus=A001&mhtOrderTimeOut=120&mhtOrderName=ordername&deviceType=02&mhtOrderType=05&responseMsg=%E6%9F%A5%E8%AF%A2%E4%BA%A4%E6%98%93%E6%88%90%E5%8A%9F&signature=ad86ba36954dbde4b9f9aee97f4132c8&responseTime=20151102100954&mhtCurrencyType=156''' 146 | try: 147 | upmv = unpackMsgRecv(recvStr,MQ001_RespList) 148 | # resultStr = pms.getResultString() 149 | recvDict = upmv.getResultDict() 150 | print(recvDict) 151 | a = upmv.verifyResponse() 152 | print(a) 153 | #upmv.test() 154 | except APIInputError as e: 155 | print("api error occured") 156 | print(e.with_traceback) 157 | except Exception as e: 158 | print("other exception") 159 | print(e.with_traceback) 160 | 161 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/utils.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8; mode: python; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=python:et:sw=4:ts=4:sts=4 2 | 3 | import os 4 | import io 5 | import sys 6 | 7 | __all__ = ['StringIO', 'parse_qsl', 'trans2unicode'] 8 | 9 | 10 | 11 | try: 12 | # When cStringIO is available 13 | import cStringIO as StringIO 14 | except ImportError: 15 | from io import StringIO 16 | 17 | try: 18 | from urlparse import parse_qsl 19 | except ImportError: 20 | # Python < 2.6 21 | from cgi import parse_qsl 22 | 23 | 24 | 25 | def trans2unicode(value): 26 | '''via this function ,every string will trans to unicode string''' 27 | if sys.version_info >= (3,0,0): 28 | # for Python 3 29 | if isinstance(value, bytes): 30 | return value.decode('utf_8') # or s = str(s)[2:-1] 31 | else: 32 | return value 33 | else: 34 | # for Python 2 35 | if isinstance(value, unicode): 36 | return str(value) 37 | else: 38 | return unicode(value) 39 | -------------------------------------------------------------------------------- /ipaynowPythonSdk/ipaynow/version.py: -------------------------------------------------------------------------------- 1 | VERSION = '1.0.0' -------------------------------------------------------------------------------- /ipaynowPythonSdk/setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | import warnings 4 | 5 | from ipaynow import VERSION 6 | 7 | try: 8 | from setuptools import setup 9 | except ImportError: 10 | from distutils.core import setup 11 | 12 | try: 13 | from distutils.command.build_py import build_py_2to3 as build_py 14 | except ImportError: 15 | from distutils.command.build_py import build_py 16 | 17 | path, script = os.path.split(sys.argv[0]) 18 | os.chdir(os.path.abspath(path)) 19 | 20 | 21 | if sys.version_info < (2, 6): 22 | warnings.warn( 23 | 'Python 2.5 is no longer officially supported by ipaynow. ' 24 | 'If you have any questions, please contact us at www.ipaynow.cn.', 25 | DeprecationWarning) 26 | 27 | 28 | 29 | # Don't import ipaynow module here, since deps may not be installed 30 | sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'ipaynow')) 31 | 32 | 33 | setup( 34 | name='ipaynow', 35 | cmdclass={'build_py': build_py}, 36 | version=VERSION, 37 | description='ipaynow python bindings', 38 | author='ipaynow', 39 | author_email='www.ipaynow.com', 40 | url='https://pay.ipaynow.cn/', 41 | packages=['ipaynow'], 42 | classifiers=[ 43 | "Development Status :: 5 - Production/Stable", 44 | "Intended Audience :: Developers", 45 | "License :: OSI Approved :: MIT License", 46 | "Operating System :: OS Independent", 47 | "Programming Language :: Python", 48 | "Programming Language :: Python :: 2", 49 | "Programming Language :: Python :: 2.6", 50 | "Programming Language :: Python :: 2.7", 51 | "Programming Language :: Python :: 3", 52 | "Programming Language :: Python :: 3.2", 53 | "Programming Language :: Python :: 3.3", 54 | "Programming Language :: Python :: 3.4", 55 | "Programming Language :: Python :: 3.5", 56 | "Programming Language :: Python :: Implementation :: PyPy", 57 | "Topic :: Software Development :: Libraries :: Python Modules", 58 | ]) 59 | --------------------------------------------------------------------------------