关于海外支付SDK的集成方案与总结

前言

因为业务的需要,公司的游戏不断的向海外拓展.自然地,我们的游戏也要根据当地的需要接入不同的支付方式.其中,最具代表性的,首当其冲的非苹果支付和谷歌支付莫属.但是,除此之外也有其他的支付方式,比如PayPal,Mycard等等.

PayPal支付

相对于国外其他的第三方支付,Paypal支付算是一个比较容易上手的第三方支付.Paypal支付移动SDK继承三种方式的支付,如下所示:

  • a) 接受信用卡和Paypal支付: 开发者能够简单地将Paypal支付和信用卡支付集成到应用中,信用卡支付手动支付和扫码支付.
  • b) 未来支付: 一旦客户将Paypal账户授权给开发者的应用中,使用Paypal支付时无需再次登录即可完成付款.
  • c) 原生支付: 用户付款时无需重定向到新页面即可完成付款

OAuth2协议

  • 1)开发者使用key和secret向Paypal服务器请求token(OAuth2协议).
  • 2)之后的请求都需要携带token认证完成操作.
  • 3)用户支付成功之后,服务端需要将利用客户端回传的数据向Paypal发起支付确认.
  • 4)当token过期失效是重新获取Token.

获取授权Token

开发者从开发者后台相应的应用上获取client_id和secret.通过这两个秘钥串想服务器请求token.

1
2
3
4
5
curl -v https://api.sandbox.paypal.com/v1/oauth2/token \
-H "Accept: application/json" \
-H "Accept-Language: en_US" \
-u "client_id:secret" \
-d "grant_type=client_credentials"

请求成功之后,响应的参数格式数如下所示:
其中, Access-Token 表示获取到token值.expires_in表示该token的过期时间.scope表示授权可请求的权限.

1
2
3
4
5
6
7
8
{
"scope": "https://uri.paypal.com/services/subscriptions https://api.paypal.com/v1/payments/.* https://api.paypal.com/v1/vault/credit-card https://uri.paypal.com/services/applications/webhooks openid https://uri.paypal.com/payments/payouts https://api.paypal.com/v1/vault/credit-card/.*",
"nonce": "2017-06-08T18:30:28ZCl54Q_OlDqP6-4D03sDT8wRiHjKrYlb5EH7Di0gRrds",
"Access-Token": "Access-Token",
"token_type": "Bearer",
"app_id": "APP-80W284485P519543T",
"expires_in": 32398
}

支付验证

开发者通过将结合用户支付成功之后从客户端回传的参数(订单号)向Paypal服务器指定的API请求支付验证.此时需要在请求头中携带token.

1
2
3
curl https://api.sandbox.paypal.com/v1/payments/payment/PAY-5YK922393D847794YKER7MUI \
-H "Content-Type: application/json" \
-H "Authorization: Bearer accessToken"

请求成功之后,响应的参数格式如下所示:
其中,environment表示请求的支付环境,分为sandbox(沙盒模式)和正式模式(live).state表示支付状态,approved表示支付验证已通过. 开发者可以通过对响应值携带的相关参数进行二次验证.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
"client":{
"environment":"sandbox",
"paypal_sdk_version":"2.0.0",
"platform":"iOS",
"product_name":"PayPal iOS SDK;"
},
"response":{
"create_time":"2014-02-12T22:29:49Z",
"id":"PAY-564191241M8701234KL57LXI",
"intent":"sale",
"state":"approved"
},
"response_type":"payment"
}

Mycard支付

Mycard支付是一个主要面向港澳台地区游戏充值代币平台,它的主要优势在于能够因地适宜的提供适合当地支付方式.按照交易模式来划分,主要分为网页支付和客户端支付两种.而按照付费方式来划分,又可以分为卡片支付、会员扣点交易、小额付款交易.

申请交易授权码

研发商在进行所有的相关的交易之前,需要向Mycard服务端申请授权码.当交易模式为Web,付费方式为INGAME,充值服务为Server-side时,此时进入网页版本支付模式.否则就是客户端支付.

客户端支付

支付流程

  • 客户端通过API向服务端发起请求,由服务端代客户端向Mycard服务端申请相关的授权码.服务端相关的代码如下所示.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function getMyCardAuthCode($arrData){
$arrGetMyCardAuthWhere = array(
"FacServiceId" => $this->arrConfigSDK['FacServiceId'],
"FacTradeSeq" => $arrData['FacTradeSeq'],
"TradeType" => $this->arrConfigSDK['TradeType'],
"ServerId" => $arrData['ServerId'],
"CustomerId" => $arrData['CustomerId'],
"PaymentType" => "",
"ItemCode" => "",
"ProductName" => strtolower(urlencode($arrData['ProductName'])),
"Amount" => $arrData['Amount'],
"Currency" => strtoupper($arrData['Currency']),
"SandBoxMode" => $this->arrConfigSDK['sandBox'],
);
$signature = $this->getPaySign($arrGetMyCardAuthWhere);
$arrGetMyCardAuthWhere['Hash'] = $signature;
$rootUrlMyCard= $this->arrConfigSDK['sandBox'] ? self::urlMyCardAuthTest : self::urlMyCardAuthB2B;
$urlMyCard = $rootUrlMyCard."?".urldecode(http_build_query($arrGetMyCardAuthWhere,NULL,"&"));
$arrGetMyCardAuth = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCardAuth);
return empty($arrGetMyCardAuth) ? array() : json_decode($arrGetMyCardAuth,true);
}
  • 客户端获取相应的授权码之后,在SDK内发起支付请求唤起支付界面,再由玩家进行支付操作.
  • 当玩家在游戏内成功完成交易之后,将申请得到的授权码再回传给我服务端请求发货.
  • 服务端获取到授权码之后先去验证交易结果,然后再进行请款,最后在请求发货.
1
2
3
4
5
6
7
8
9
10
11
12
13
function getMyCardTradeQuery($arrData){
if(!empty($arrData['AuthCode'])){
$arrAuthCode = array(
"AuthCode" => $arrData['AuthCode']
);
$rootUrlMyCard = $this->arrConfigSDK['sandBox'] ? self::urlMyCardQueryTest : self::urlMyCardQueryB2B;
$urlMyCard = $rootUrlMyCard."?".http_build_query($arrAuthCode,NULL,"&");
$arrGetMyCard = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCard);
$arrRst = empty($arrGetMyCard) ? array() : json_decode($arrGetMyCard,true);
}
return empty($arrRst) ? array() : $arrRst;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
function getMyCardPaymentConfirm($arrData){
if(!empty($arrData['AuthCode'])){
$arrAuthCode = array(
"AuthCode" => $arrData['AuthCode']
);
$rootUrlMyCard = $this->arrConfigSDK['sandBox'] ? self::urlMyCardConfirmTest : self::urlMyCardConfirmB2B;
$urlMyCard = $rootUrlMyCard."?".http_build_query($arrAuthCode,NULL,"&");
$arrGetMyCard = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCard);
$arrRst = empty($arrGetMyCard) ? array() : json_decode($arrGetMyCard,true);
}
return empty($arrRst) ? array() : $arrRst;
}

网页版支付

进入网页版支付模式下,网页支付可分为自定义页面以及官方推荐页面.

支付流程

  • 玩家选择指定的充值档位之后需要通过Ajax向服务端发起请求,由服务端代网页端向Mycard服务端申请相关的授权码.服务端相关的代码略.
  • 玩家需要填写支付的点卡信息,网页需要将授权码和相关的点卡信息给服务端先进行验证,再进行请款,最后再请求发货.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function getMyCardPayInGamePay($arrData){
if(!empty($arrData['AuthCode']) && !empty($arrData['CardID']) && !empty($arrData['CardPW'])){
$arrMyCardInGamePayWhere = array(
"AuthCode" => $arrData['AuthCode'],
"CardID" => $arrData['CardID'],
"CardPW" => $arrData['CardPW'],
);
$signature = $this->getPaySign($arrMyCardInGamePayWhere);
$arrMyCardInGamePayWhere['Hash'] = $signature;
$rootUrlMyCard = $this->arrConfigSDK['sandBox'] ? self::urlMyCardInGamePayTest : self::urlMyCardInGamePayB2B;
$urlMyCard = $rootUrlMyCard."?".http_build_query($arrMyCardInGamePayWhere,NULL,"&");
$arrGetMyCard = $this->paySDK->curlPayByGet($urlMyCard);
$this->logRequest($urlMyCard.PHP_EOL.$arrGetMyCard);
$arrRst = empty($arrGetMyCard) ? array() : json_decode($arrGetMyCard,true);
}
return empty($arrRst) ? array() : $arrRst;
}

思考

参考资料

文章目录
  1. 1. 前言
  2. 2. PayPal支付
    1. 2.1. OAuth2协议
    2. 2.2. 获取授权Token
    3. 2.3. 支付验证
  3. 3. Mycard支付
    1. 3.1. 客户端支付
      1. 3.1.1. 支付流程
    2. 3.2. 网页版支付
      1. 3.2.1. 支付流程
  4. 4. 思考
  5. 5. 参考资料