最近公司做了个项目 投放市场在澳门,澳门那边的支付环境主要使用澳门通(以下使用MPay代替),所以在做支付功能的时候,就有了MPay集成需求。初听到这个消息的时候,作为一名工作积极份子,立马开始了一顿猛如虎的操作——百度、谷歌、简书、GitHub等各大平台各种搜索,结果无奈的发现,均没有关于iOS MPay集成这方面的资料,可能是因为比较小众的缘故,咱忍了。
因为在澳门通集成过程中几经波折,也碰到过些坑,在完成之后,回头发现本来很简单的事情,因为不熟悉,以及在与澳方沟通过程花费了大量时间,所以将自己的血泪历程与MPay集成方法,以及碰到的坑,分享给大家,希望大家在开发过程中能节省点宝贵的时间及少趟点坑,权当抛砖引玉。
MPay 在打包静态库的时候,已经将 微信 打包进了SDK,所以如果项目在调用 微信 的时候,只能使用 MPay内部集成的 微信 支付,如果外界想要单独调用 微信支付的时候,在导入 微信 SDK的时候,就会报 重复导入 的错误。这是一个坑,要留意一下!
所以,以下分为三个步骤来说明 MPAy 支付,MPay调用 支付宝 ,MPay调用微信 。
澳门通与商户之间通过交换报文与资料档案来交换业务资讯、实现业务流程、控制业务规则。双方的交互模式可以归纳为请求-应答、单向通知、文档上传与文档下载这四种模式,实际业务中可能会将各种交互模式结合起来使用。下文将介绍这四种交互模式适用的场景与实现方式。
1、请求(Request)-应答(Response)模式:
在请求-应答模式下,一方作为服务提供者,另一方作为服务使用者。由服 务使用者主动向服务提供者发起请求并等待应答,服务提供者接受请求,完成 处理,并向服务使用者应答处理结果,服务使用者收到处理结果之后进行后续 处理。
请求-应答模式适用于服务使用者需要根据服务提供者的服务应答才能进行 正确的后续处理的场景。 本文中,服务使用者指商户的系统设施及服务,服务提供者指澳门通及其相应 的系统设施及服务。
2、单向通知模式:
在单向通知模式下,一方作为通知发送者,一方作为通知接收者。发送者发送通知,并保证接收者收到通知。通知接收者在收到通知之后,立即返回发送者通知已收到。通知送达之后,发送方与接收方可以独立地进行后续业务处理。如果对方进行业务处理所需的时间不可预知时,采用单向通知模式。单向通知模式可以单独使用,也可以作为其它交互模式的一部分使用,因此,单向模式适用于澳门通主动通知商户交易处理成功。
一:MPaySDK支付集成流程
1:由MPay iOS端提供的 MPaySDK.framework静态库引入到工程项目中(目前不支持Cocopods);
在需要支付的类中导入 #import <MPaySDK/MPaySDK.h> 文件路径
2:Command+B 编译一下,报错导入以下类:
libsqlite3.tbd
libc++.tbd
libz.tbd
libc.tbd
CoreMotion.framework
CFNetwork.framework
SystemConfiguration.framework
CoreTelephony.framework
QuartzCore.framework
CoreText.framework
CoreGraphics.framework
Foundation.framework
UIKit.framework
编译,完美通过
3:Target - info -URL Types 配置URL Types 设置自己项目的URL Schems,以便调用SDK方法的时候使用
因为UAT测试环境,生产环境服务器的https应用层不
支持ATS设置,如果应用程式基于9.0编译,由于iOS9.0中https应用程序传输安全(ATS)的限制,我们需要设置:NSAppTransportSecurity 的 Allow Arbitrary Loads 为 YES
4、支付环境设置
在MPaySDK.h文件中可以查看环境变量的枚举值
0:MPay_SIT 代表MPay SIT 环境
1: MPay_UAT 代表MPay UAT环境
2:MPay_Prod 代表MPay 生产环境
通过实例方法进行UAT环境配置
例:[[MPaySDKsharedInstance] setEnvironmentType:MPay_UAT];
5、支付方法调用
/**
商戶使用(MPay)
@param params 商戶簽名后的订單數據
@param schema 商戶APP的url schema
@param sender 當前控制器
@param delegate 實現協議方法的代理對象
*/
-(void)MPayWithParams:(NSDictionary *)params withSchema:(NSString *)schema WithSender:(id)sender withDelegate:(id<MPaySDKDelegate>)delegate;
6、params 参数说明
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
---|---|---|---|---|---|
app_id | String | 必须 | 32 | MacauPay分配给开发者的应用ID | 2014072300007148 |
api_name | String | 必须 | 30 | 接口名称 | preCreate |
biz_api_code | String | 必须 | 30 | 接口功能 | 100020007 |
data_type | String | 可选 | 40 | 仅支持JSON | JSON |
charset | String | 必须 | 10 | 请求使用的编码格式,如utf-8,gbk,gb2312等 | utf-8 |
sign_type | String | 必须 | 10 | 商户生成签名字符串所使用的签名算法类型,目前支持RSA | RSA |
sign | String | 必须 | 256 | 商户请求参数的签名串,详见签名 | 详见示例,6.4.私钥生成请求签名章节 |
timestamp | String | 必须 | 19 | 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" | 2014-07-24 03:07:50 |
version | String | 必须 | 3 | 调用的接口版本,固定为:1.0 | 1.0 |
biz_content | String | 必须 | - | 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 | 参考下面 |
● biz_content 说明
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
---|---|---|---|---|---|
out_trade_no | String | 必须 | 64 | 商户订单号,64个字符以内、只能包含字母、数字、下划线;需保证在商户端不重复 | 20150320010101001 |
total_amount | Price | 必须 | 9 | 订单总金额,单位为元,精确到小数点后两位,取值范围[0.01,100000000] | 88.88 |
subject | String | 必须 | 256 | 订单标题 | Iphone6 16G |
trade_mode | String | 必须 | 10 | 0001担保支付,0002即时到账,默认:0002 | 0002即时到账 |
body | String | 可选 | 128 | 对交易或商品的描述 | Iphone6 16G |
buyer_logon_id | String | 可选 | 100 | 买家MacauPay账号,和 buyer_user_id不能同时为空 | 15901825620 |
buyer_user_id | String | 可选 | 28 | 买家在MacauPay的用户id | 2088101117955611 |
operator_id | String | 可选 | 28 | 商户操作员编号 | Yx_001 |
store_id | String | 可选 | 32 | 商户门店编号 | NJ_001 |
terminal_id | String | 可选 | 32 | 商户机具终端编号 | NJ_T_001 |
timeout_express | String | 可选 | 6 | 该笔订单允许的最晚付款时间,逾期将关闭交易。取值范围:1m~15d。m-分钟,h-小时,d-天,1c-当天(1c-当天的情况下,无论交易何时创建,都在0点关闭)。该参数数值不接受小数点,如 1.5h,可转换为 90m。默认90m | 90m |
submerchant_id | String | 可选 | 32 | 二级商户号,与MacauPay约定按照MCC收手续费时使用 | 2016041400077000000003314986 |
currency | String | 可选 | 6 | 默认MOP | MOP |
notify_url | String | 可选 | 256 | MacauPay服务器主动異步通知商户服务器里指定的页面http/https路径。 | http://api.test.net/atinterface/receive_n |
return_url | String | 可选 | 256 | MacauPay服务器主动同步通知商户服务器里指定的页面http/https路径。 | http://api.test.net/atinterface/receive_n |
goods_detail | GoodsDetail [] | 可选 | - | 订单包含的商品列表信息.Json格式. 其它说明详见:“商品明细说明” | [{"order_no":"201604141231231231231222","goods_id":"apple-01","goods_name":"ipad","goods_category":"7788230","price":"2000.00","quantity":"1"}] |
order_no | String | 必填 | 64 | 商品明细订单号 | 2016041400077000000003 |
goods_id | String | 必填 | 32 | 商品的编号 | apple-01 |
goods_name | String | 必填 | 256 | 商品名称 | ipad |
quantity | Number | 必填 | 10 | 商品数量 | 1 |
price | Price | 必填 | 9 | 商品单价,单位为元 | 2000 |
body | String | 可选 | 1000 | 商品描述信息 | 特价手机 |
show_url | String | 可选 | 400 | 商品的图片地址 | http://www.alipay.com/xxx.jpg |
7、方法具体实现:
//签名地址 - 要改成贵公司服务器 api 地址
NSString*signUrl = @"xxxx";
//签完名之后拿到服务器返回的NSDictionary类型数据,作为参数
//調起支付
if(params) {
[[MPaySDK sharedInstance]MPayWithParams:params withSchema:@"macaupayF2823" WithSender:self withDelegate:self];
}
8、在响应事件 控制器中遵循代理协议
@interface ViewController ()<MPaySDKDelegate>
实现代理方法
//实现支付完成或者取消之后的回调结果(注意兼容ios8的方法)
//在需要处理结果的地方实现MPaySDKDelegate协议方法 处理展示结果逻辑
/**
支付成功回调
@paramstatus 支付狀態標誌 true成功 false 失敗
@paramorder 訂單信息
*/
-(void)MPaySDK_WithPayStatus:(bool)status WithOrder:(NSDictionary*)order;
/**
支付失败回调
@paramerrorInfo 錯誤信息
@paramerrorCode 錯誤碼
*/
-(void)MPaySDK_WithFailed:(NSString*)errorInfo withErrorCode:(NSString*)errorCode;
9、支付回调及响应状态
在项目AppDelegate.m里面的回调方法
-(BOOL)application:(UIApplication*)app openURL:(NSURL*)url options:(NSDictionary *)options{
//里面调用
[[MPaySDK sharedInstance]ProcessOrderWithPaymentResult:url];
return true;
}
-(BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation
{
//回调方法,必調
[[MPaySDK sharedInstance] ProcessOrderWithPaymentResult:url];
return true;
}
10、支付状态码
Code | ResultMsg |
---|---|
9000 | 订单支付成功 |
6002 | 网络连接出错 |
6001 | 用户中途取消 |
5000 | 支付异常 |
4044 | 訂單金額無效 |
4004 | 无效订單 |
4000 | 订单支付失败 |
1000 | 簽名失敗 |
0001 | 手續費大於交易金額 |
1002 | 數據格式錯誤 |
二:AliPaySDK支付集成流程
AliPay 和 MPay 前期配置相同,导入MPaySDK.framework静态库,并且需要导入AliPaySDK 包文件,只不过支付方法和 上传参数,这里只说明有区别的点,其它参考 上面 MPay,AliPaySDK支付状态码参考同MPaySDK支付状态码
1、支付方法调用
/**
商户使用(支付宝)
@paramparams 商戶簽名后的訂單數據
@paramScheme 商戶APP的url schema
@paramdelegate 實現協議方法的代理對象
*/
-(void)AliPayWithParams:(NSDictionary*)params withScheme:(NSString*)Scheme with:(id)delegate;
2、params参数说明
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
---|---|---|---|---|---|
app_id | String | 必须 | 32 | MacauPay分配给开发者的应用ID | 2014072300007148 |
api_name | String | 必须 | 30 | 接口名称 | aliNoAccPay |
biz_api_code | String | 必须 | 30 | 接口功能 | 100020008 |
data_type | String | 可选 | 40 | 仅支持JSON | JSON |
charset | String | 必须 | 10 | 请求使用的编码格式,如utf-8,gbk,gb2312等 | utf-8 |
sign_type | String | 必须 | 10 | 商户生成签名字符串所使用的签名算法类型,目前支持RSA | RSA |
sign | String | 必须 | 256 | 商户请求参数的签名串,详见签名 | 详见示例,6.4.私钥生成请求签名章节 |
timestamp | String | 必须 | 19 | 发送请求的时间,格式"yyyy-MM-dd HH:mm:ss" | 2014-07-24 03:07:50 |
version | String | 必须 | 3 | 调用的接口版本,固定为:1.0 | 1.0 |
biz_content | String | 必须 | - | 请求参数的集合,最大长度不限,除公共参数外所有请求参数都必须放在这个参数中传递,具体参照各产品快速接入文档 | 参考下面 |
● biz_content 说明
参考macauPay的参数说明
3、方法具体实现:
//a、签名地址 - 要改成贵公司服务器 api 地址
NSString*signUrl = @"xxxx";
//b、签完名之后拿到服务器返回的NSDictionary类型数据,作为参数
//調起支付
if(params) {
[[MPaySDK sharedInstance] AliPayWithParams:params withScheme:@"macaupayF2823" with:self];
}
三:WechatPaySDK支付集成流程
由MPay iOS端提供的sdk文件,MPaySDK.framework 静态库引用到工程项目中(如果已经引入,无需重复引入):并且需要导入WechatPay支付所需要的文件和静态库:libWeChatSDK.a, WechatAuthSDK.h, WXApi.h, WXApiObject.当已经再开放平台已经注册应用并且报备之后,再项目工程里面的AppDelegate.h文件中导入的WXApi.h ,并且在didFinishLaunchingWithOptions 方法中向微信发起注册:
例:[WXApi registerApp:@"xxxx" enableMTA:NO];
在需要支付的类中导入MPaySDK.h文件路径即可。
1、支付方法调用
/**
商户使用(微信)
@paramparams 商戶簽名后的訂單數據
@paramScheme 商戶APP在開放平台註冊的appid
@paramdelegate 實現協議方法的代理對象
*/
-(void)WeChatPayWithParams:(NSDictionary*)params withScheme:(NSString*)Scheme with:(id)delegate;
2、params参数说明
参数 | 类型 | 是否必填 | 最大长度 | 描述 | 示例值 |
---|---|---|---|---|---|
appid | String | 必须 | 32 | 微信分配给开发者的应用ID | wxb4ba3c02aa476ea1 |
partnerid | String | 必须 | 32 | 商户号 | 1900000109 |
package | String | 必须 | 128 | 扩展字段 | Sign=WXPay |
noncestr | String | 可选 | 32 | 随机字符串 | 5K8264ILTKCH16CQ2502SI8ZNMTM67VS |
timestamp | String | 必须 | 10 | 时间戳 | 1412000000 |
prepayid | String | 必须 | 32 | 预支付交易会话ID | 微信返回的支付交易会话ID |
sign | String | 必须 | 32 | 签名 | C380BEC2BFD727A4B6845133519F3AD6 |
3、方法具体实现:
//a、签名地址 - 要改成贵公司服务器 api 地址
NSString*signUrl = @"xxxx";
//b、签完名之后拿到服务器返回的NSDictionary类型数据,作为参数
//調起支付
if(params) {
[[MPaySDK sharedInstance] WeChatPayWithParams:params withScheme:@"macaupayF2823" with:self];
}
4、支付回调及响应状态
参考同MPaySDK支付回调及响应状态
5、支付状态码
ResultStatus | Result |
---|---|
9000 | 訂單支付成功 |
6001 | 用戶中途取消 |
6005 | 微信支付:簽名錯誤、未註冊APPID、項目設置APPID不正確、註冊的APPID與設置的不匹配、其他異常等. |
以上就是 MPay iOS端集成的全部过程,如有疑问欢迎留言指正。😀